微服务篇-C 深入理解第一代微服务(SpringCloud)_VI 深入理解Zuul服务网关

原创作者:田超凡(程序员田宝宝)

版权所有,引用请注明原作者,严禁复制转载

Part 1 理论部分

1 网关类别有哪些?

常见的网关类别有三种:开放API(Open API)网关、微服务网关、API服务管理平台。

1 开放API(Open API)网关:

在开放API(Open API)中,客户需要将自身的数据、能力等作为开放平台对外开放,通常会以REST的方式对外提供,比如阿里云的开放平台、腾讯的QQ开放平台、微信开放平台等等,Open API开放平台必然会涉及到用户的应用接入、API权限管理、调用次数管理等,所以必然会有一个统一的入口来进行管理,这正是开放API(Open API)网关可以发挥作用的时候。

2 微服务网关:

微服务的概念最早是在2012年提出的,在SpringCloud的大力推广下,微服务在2014年后才逐渐得到了大力发展,在微服务架构中,有一个组件必不可少,那就是微服务网关,微服务网关实现了负载均衡、缓存、路由、访问控制、服务代理、监控、日志等功能,API网关在微服务架构中正是以微服务网关的身份存在。

3 API服务管理平台:

上述的微服务架构对一些企业来说可能存在实施上的困难,因为企业有很多遗留系统,如果要将这些遗留系统全部抽取改造成微服务架构的话,会导致改动量大大增加,且需要部署的服务器数量也会增多,这对企业来说成本太高,但是不同的系统之间存在大量的API服务相互调用,所以需要对系统间的服务调用进行管理,可以清晰地看到各系统之间的调用关系,对系统间的调用行为进行监控,API网关可以解决这些问题,如果没有大规模地实施微服务架构,那么对企业来说微服务网关就是企业的API服务管理平台。

2 网关作用是什么?

网关的作用是可以实现负载均衡、路由转发、日志、权限控制、监控等功能。

3 网关和拦截器、过滤器的区别是什么?

网关是拦截所有服务器的请求进行控制

拦截器是拦截某单个服务器的请求进行控制

过滤器是拦截某单个服务器的请求进行过滤,只放行符合过滤条件的请求。

4 如何设计微服务网关?

设计微服务网关包括开放API接口和内网API接口。

开放API接口:

对于Open API使用的API网关来说,一般合作伙伴要以应用的形式接入到Open API开放平台,然后需要到Open API开放平台申请应用,因此在Open API网关之外,需要有一个面向合作伙伴的使用平台,这就要求Open API网关需要提供API给这个用户平台进行访问。

当然如果是在简单的场景下,可能不需要提供一个面向合作伙伴的门户,只需要让公司的运营人员直接添加合作伙伴应用的应用ID/密钥等,这种情况下也就不需要合作伙伴门户子系统。

内网API接口:

对于内网的API网关来说,起到的作用上可以认为是微服务网关,也可以认为是内网的API服务管理平台,当企业将所有的应用都使用微服务架构管理起来的时候,API网关就起到了微服务网关的作用,当企业只是将系统和系统之间的调用使用REST API的方式进行访问时,使用API网关对调用进行管理,API网关就起到了API服务管理平台的作用。

对于公司内部公网应用(如APP、公司网站),如果管理的比较细致,在架构上可以使用单独的API网关来处理这部分内部公网应用,如果想要使用比较简单的方式实现,可以使用面向合作伙伴的API网关,如果使用独立的API网关,有以下几种好处:

1 面向合作伙伴和面向公司主体业务的优先级不一样,不同的API网关可以实现业务影响的隔离。

2 内网API使用的管理流程和面向合作伙伴的管理流程可能不一样。

3 内网API在功能扩展等方面的需求量一般会大于Open API在功能扩展等方面的需求量。

基于以上的分析,如果公司有能力,还是建议分开使用合作伙伴Open API网关和内部公网应用网关。

5 Nginx和Zuul的区别是什么?

Nginx是采用服务器负载均衡进行转发

Zuul依赖于Ribbon和Eureka实现本地负载均衡转发,

Zuul默认已经整合并开启了Ribbon实现的客户端负载均衡的功能,

Nginx功能比Zuul功能更加强大,能够整合其他的语言比如Lua脚本实现强大的功能,同时Nginx还可以更好地抗高并发,Zuul网关适用于一般请求过滤和拦截等。

6 动态网关实现思路是什么?

传统方式是将路由规则配置到配置文件中,如果路由规则发生了改变,需要重启服务器,可以整合SpringCloud Config分布式配置中心,实现动态路由规则网关。

Part 2 实践部分

Zuul网关

zuul是spring cloud的一个推荐组件:https://github.com/Netflix/zuul

使用Zuul实现反向代理
环境搭建
Maven依赖信息

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.1.RELEASE</version> </parent> <!-- 管理依赖 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.M7</version> <type>++pom++ </type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-++netflix++ -++zuul++</artifactId> </dependency> <!-- SpringBoot整合++eureka++客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-++netflix++ -++eureka++-client</artifactId> </dependency> </dependencies> <!-- 注意: 这里必须要添加, 否者各种依赖有问题 --> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone\</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> |

application.yml

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ###注册 中心 eureka: client: ++serviceUrl++ : defaultZone: http://localhost:8100/eureka/ server: port: 80 ###网关名称 spring: application: name: service-zuul ### 配置网关反向代理 ++zuul++ : routes: api-a: ### 以 /api-member/访问转发到用户服务 path: /api-member/** serviceId: app-ittcf-member api-b: ### 以 /api-order/访问转发到订单服务 path: /api-order/** serviceId: app-ittcf-order |

使用Zuul整合Ribbon

Zuul 默认开启了 Ribbon本地负载均衡功能。

使用Zuul过滤器

案例:使用过滤器验证客户端是否有登陆。

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| @Component public class TokenFilter extends ZuulFilter { public Object run() throws ZuulException { // 获取上下文 RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); String userToken = ++request++.getParameter("userToken"); if (StringUtils.isEmpty(userToken)) { currentContext.setSendZuulResponse(false ); currentContext.setResponseStatusCode(401); currentContext.setResponseBody("userToken is null"); return null ; } // 否则正常执行业务逻辑..... return null ; } // 判断过滤器是否生效 public boolean shouldFilter() { return true ; } // 过滤器的执行顺序。当请求在一个阶段的时候存在多个多个过滤器时,需要根据该方法的返回值依次执行 public int filterOrder() { return 0; } // 过滤器类型 ++pre++ 表示在 请求之前进行拦截 public String filterType() { return "pre"; } } |

动态网关

传统方式将路由规则配置在配置文件中,如果路由规则发生了改变,需要重启服务器。这时候我们可以整合SpringCloud Config分布式配置中心,实现动态路由规则。

在git上创建一个文件service-zuul-dev.yml

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ### 配置网关反向代理 zuul: routes: api-a: ### 以 /api-member/访问转发到用户服务 path: /api-member/** serviceId: app-ittcf-member api-b: ### 以 /api-order/访问转发到订单服务 path: /api-order/** serviceId: app-ittcf-order |

Maven依赖信息

新增监控中心依赖信息

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| <!-- actuator监控中心 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- ++springcloud++ ++config++ 2.0 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-++config++-client</artifactId> </dependency> |

application.yml

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ###服务注册地址 eureka: client: ++serviceUrl++ : defaultZone: http://localhost:8100/eureka/ ###api网关端口号 server: port: 80 ###网关名称 spring: application: name: service-zuul cloud: config: ####读取后缀 profile: dev ####读取config-server注册地址 discovery: service-id: config-server enabled: true ###默认服务读取eureka注册服务列表 默认间隔30秒 ###开启所有监控中心接口 management: endpoints: web: exposure: include: "*" |

项目启动

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| // ++zuul++配置能够使用++config++实现实时更新 @RefreshScope @ConfigurationProperties("zuul") public ZuulProperties zuulProperties() { return new ZuulProperties(); } |

手动刷新接口

http://127.0.0.1/actuator/refresh

Zuul网关集群

Zuul网关集群使用Nginx反向代理即可,保证每台网关配置数据相同。

nginx.conf配置参考:

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| upstream backServer{ server 127.0.0.1:81; server 127.0.0.1:82; } server { listen 80; server_name wg.ittcf.com; location / { ### 指定上游服务器负载均衡服务器 proxy_pass http://backServer/; index index.html index.htm; } } |

本文部分素材转载自蚂蚁课堂

相关推荐
m0_5719575831 分钟前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
魔道不误砍柴功3 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2343 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨3 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
测开小菜鸟4 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
P.H. Infinity5 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天5 小时前
java的threadlocal为何内存泄漏
java
caridle5 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
^velpro^5 小时前
数据库连接池的创建
java·开发语言·数据库
苹果醋36 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx