基于SpringCloud Gateway搭建网关服务
一、问题背景
1.微服务架构的普及
随着微服务架构的兴起,企业应用系统的开发越来越倾向于以分布式、松耦合的方式进行构建。微服务架构中存在大量的服务实例,需要一个中心化的入口来处理流量路由、负载均衡等问题。
2. API网关的需求
微服务架构中,前端应用需要与多个微服务进行交互,每个微服务通常都有自己的RESTful API。API网关作为一个中心化的入口,可以对请求进行路由、转发和过滤,从而简化前端应用的逻辑复杂度。
3.复杂的业务场景
微服务架构通常会涉及多个服务实例、多个环境(如开发、测试、生产环境)、多个版本等复杂的业务场景。需要一个灵活、可配置的网关来处理不同环境和版本之间的请求路由和流量控制。
4.安全性需求
在金融、医疗等行业,对数据安全和隐私保护的要求非常高。Spring Cloud Gateway提供了丰富的安全功能,如HTTPS支持、OAuth2认证、IP黑白名单、请求限流等,能够帮助企业确保服务的安全性。
5.性能和扩展性需求
对于互联网行业或大型企业来说,高性能和良好的扩展性是非常重要的。Spring Cloud Gateway基于响应式编程模型和异步IO技术,具有优异的性能表现和良好的扩展性,可以满足高并发和大流量的需求。
二、SpringCloud Gateway简介
1.定义
SpringCloud GateWay是众多网关解决方案的一种。它是Spring Cloud的⼀个全新项⽬,⽬标是取代Netflix Zuul,它基于Spring5.0 + SpringBoot2.0 + WebFlux(基于⾼性能的Reactor模式响应式通信框架Netty,异步⾮阻塞模型)等技术开发,性能⾼于Zuul,官⽅测试,GateWay是Zuul的1.6倍,旨在为微服务架构提供⼀种简单有效的统⼀的API路由管理⽅式。
2.作用
(1)路由转发
将客户端的请求按照预先定义的规则转发到对应的后端服务,实现请求的路由功能。
(2)负载均衡
在路由转发时,可以实现负载均衡策略,将请求分发到多个后端服务实例上,从而提高系统的可用性和性能。分类如下:
|
名称 |
作用 |
使用方法 |
|
RoundRobin 轮询策略 |
按照顺序将请求分配给后端服务实例,每个实例依次轮流接收请求 |
使用 lb://service-name 形式的 URI,并且不指定负载均衡策略,默认走的是这个轮询策略 |
|
WeightedResponseTime 加权响应时间策略 |
根据服务实例的响应时间来进行加权负载均衡,响应时间较快的实例将会收到更多的请求 |
|
|
Retry 重试策略 |
在请求失败时进行重试,可以提高系统的容错能力和稳定性。当某个服务实例无法处理请求时,Retry 策略会自动将请求重新发送给其他可用的实例,直到达到最大重试次数 |
|
|
ZonePreference 区域优先策略 |
允许您优先选择指定区域内的服务实例,这对于多地区部署的系统非常有用 |
|
|
Custom 自定义策略 |
根据自身需求定义自定义的负载均衡策略。您可以根据具体业务逻辑和性能需求编写自己的策略 |
编写一个实现了 RoutePredicateFactory 接口的自定义策略工厂类,并在配置文件中使用该工厂类指定路由规则 |
(3)安全认证
可以通过配置认证过滤器对请求进行安全认证,实现访问控制(黑名单)、身份验证等安全功能。
(4)请求过滤
支持通过过滤器链对请求进行拦截、处理和转换,实现请求的预处理、日志记录、请求修改等功能。
(5)流量控制
支持通过过滤器实现流量控制功能,如限流、熔断等,保护后端服务免受异常流量影响。
(6)监控和日志
提供了监控和日志记录功能,可以实时监控网关的运行状态、流量情况和服务调用情况,帮助运维人员及时发现和解决问题。
(7)动态路由
支持动态路由配置,可以根据请求的条件(如URI、请求头、请求参数等)进行动态路由,实现灵活的请求转发和路由管理。
(8)灰度发布和AB测试
可以通过路由配置实现灰度发布和AB测试功能,根据不同条件将请求路由到不同的服务版本或后端实例上,帮助企业降低发布风险和提高发布效率。
(9)请求重试和重定向
支持通过过滤器实现请求重试和重定向功能,保证请求的可靠性和稳定性。
(10)统一异常处理
提供了统一的异常处理机制,可以对网关和后端服务的异常进行统一处理和转换,提高系统的健壮性和可靠性。
3.优势
|
|
Gateway |
Zuul |
|
I/O |
异步IO技术,具有优异的性能和高并发能力 |
传统的阻塞IO模型,性能和扩展性相对较低 |
|
定制性 |
支持自定义过滤器的扩展和定制,满足各种复杂的业务需求 |
过滤器功能相对简单,定制性较差 |
|
配置 |
支持动态路由和基于条件的路由配置,灵活性更强 |
由配置相对静态,不够灵活 |
|
扩展性 |
提供了丰富的扩展点和插件机制,具有更好的可扩展性和可定制性 |
Zuul的扩展性和定制性较差,很难满足复杂业务场景下的需求 |
表1 Gateway与Zuul的对比优势
4.网关在架构中的位置

图1 网关在架构中的位置
如图1所示,展示了网关在微服务架构里所处在的位置。首先,外部各端的请求先到达代理层,一般为Nginx,通过它来实现网关的高可用。接着,Nginx按照配置的负载均衡策略把请求转发到对应网关实例。最后,由网关进行API路由到下游的微服务实例。
三、SpringCloud Gateway核心概念
1.路由(route):是⽹关⽐较基础的⼯作单元。路由由⼀个ID、⼀个⽬标URL(最终路由到的地址)、⼀系列的断⾔(匹配条件判断)和Filter过滤器(精细化控制)组成。如果断⾔为true,则匹配该路由。
2.断⾔(predicates):参考了Java8中的断⾔java.util.function.Predicate,开发⼈员可以匹配Http请求中的所有内容(包括请求头、请求参数等)(类似于nginx中的location匹配⼀样),如果断⾔与请求相匹配则路由。常见分类如下:

3.过滤器(filter):⼀个标准的Spring webFilter,使⽤过滤器,可以在请求之前或者之后执⾏业务逻辑。
四、SpringCloud Gateway工作流程
1.基本流程图

图4 Gateway工作流程图
如图4所示,客户端向Spring Cloud GateWay发出请求,然后在GateWay Handler Mapping中找到与请求相匹配的路由,将其发送到GateWay Web Handler;Handler再通过指定的过滤器链来将请求发送到我们实际的服务执⾏业务逻辑,然后返回。过滤器之间⽤虚线分开是因为过滤器可能会在发送代理请求之前(pre)或者之后(post)执⾏业务逻辑。总的来说,Gateway的核心逻辑为路由转发+执行过滤器链。
五、SpringCloud Gateway基本使用
参考代码:https://gitee.com/li_kang_wen/gateway-demo
1.创建Gateway服务模块,并注册到Nacos注册中心
(1)使用
1)添加Gateway核心依赖

2)添加Gateway服务配置

3)添加Gateway业务配置

(2)验证

2.创建服务提供者模块,并注册到Nacos注册中心
(1)使用
1)添加web相关依赖

2)添加服务提供者服务配置

3)添加服务提供者业务配置


4)添加模拟控制器

(2)验证

3.Gateway【路由转发】功能
(1)使用
1)在配置中心页面给gateway服务新建配置文件
2)配置内容如下

3)执行流程说明
通过配置断言Path以及路由地址uri,gateway接收到请求后对进行拦截处理:如果判断请求Path满足断言定义的匹配条件,则会将该请求转发到指定的这个uri地址。
(2)验证

在浏览器上,访问网关服务地址及服务提供者模块接口url,能成功返回结果,说明此处网关进行路由转发成功。
4.Gateway【动态路由】功能
(1)使用
1)修改上述小节3.的gateway配置文件
2)配置内容如下

主要是把路由规则里的uri由静态地址改为lb://服务名的形式。
3)在IDEA里,分别开启两个服务提供者的实例,一个为9002,另一个为9003


4)流程说明
在网关服务启动或后续不定期的时间里,gateway都是通过注册中心客户端接收服务器端推送的服务实例列表信息,gateway会此进行维护更新。后面接收前端访问到的请求时,gateway对进行拦截处理:如果判断请求Path满足断言定义的匹配条件,则会将根据uri配置的服务名,获取对应的服务实例列表,然后再通过负载均衡器选择其中一个实例地址进行请求转发。
(2)验证

通过访问网关服务即9090,能成功访问到下游服务实例中的一个。
5.Gateway【过滤器】功能
(1)简介
1)从过滤器⽣命周期(影响时机点)的⻆度来说,主要有两个pre和post:
|
⽣命周期时机点 |
作⽤ |
|
pre |
这种过滤器在请求被路由之前调⽤。我们可利⽤这种过滤器实现身份验证、在集群中选择 请求的微服务、记录调试信息等。 |
|
post |
这种过滤器在路由到微服务以后执⾏。这种过滤器可⽤来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。 |
2)从过滤器类型的⻆度,Spring Cloud GateWay的过滤器分为GateWayFilter和GlobalFilter两种
|
过滤器类型 |
影响范围 |
|
GateWayFilter |
应⽤到单个路由路由上 |
|
GlobalFilter |
应⽤到所有的路由上 |
(2)使用
1)需求:⾃定义全局过滤器实现IP访问限制(⿊⽩名单)。
2)实现方法
A. 自定义全局过滤器类,实现GlobalFilter, Ordered接口
B. 分别重写filter方法和order方法
C. 在filter方法进行黑名单判断的业务处理


3)验证
1.失败场景:把本机IP设置到黑名单中,本机发起访问,限制效果生效


2.成功场景:把本机IP设置到黑名单中,非本机发起访问,成功放行

六、SpringCloud Gateway的FAQ
1.可能会遇到的问题以及对应解决方案
(1)网关宕机问题
【问题描述】
⽹关作为⾮常核⼼的⼀个部件,如果挂掉,那么所有请求都可能⽆法路由处理。
【解决方案】
我们需要做GateWay的⾼可⽤。GateWay的⾼可⽤很简单:可以启动多个GateWay实例来实现⾼可⽤,在GateWay的上游使⽤Nginx等负载均衡设备进⾏负载转发以达到⾼可⽤的⽬的。

(2)动态路由失败,报“503:03 SERVICE_UNAVAILABLE "Unable to find instance for xxx”
【问题描述】 Gateway根据服务名从Nacos注册中心找不到对应实例

【原因】
1)通过对gateway代码断点以及查询接收注册中心消息的日志,确认从注册中心拿不到服务提供者testprovider的实例

2)已排除非“服务实例未成功注册到注册中心”或“服务实例的健康状态为异常”或“路由使用的服务名称与下游服务自定义的名称不一致”的原因
经分析,猜想是否因为网关和服务提供者不属于同一分组下,由于隔离产生了权限限制,导致拿不到注册中心的服务列表。接着通过把服务提供者调整到跟网关同一分组下,发现网关服务能拿到服务提供者列表了,猜想得到了验证。

修改前:在gateway的负载均衡处理时,拿到的serviceInstances为null

修改后:在gateway的负载均衡处理时,拿到的serviceInstances为2个,刚好对应服务提供者testprovider的两个实例,分别为9002和9003。


【解决方案】
把服务提供者和网关放在注册中心的同个分组里即可。
(3)动态路由失败,报“404:找不到URI资源”
【问题描述】
在请求以下url,会报“404”
http://192.168.75.38:9090/testprovider/check/getNacosConfigStr/123456?endStr=HelloWorld
【原因】经断点,发现gateway的request少了路径的第一个占位符/testprovider

经确认,gateway在动态路由时,如果path的第一个占位符跟服务名即service-id相同,则会自动把它剔除。
【解决方案】
下游服务的请求路径(servlet.context-path)配置为/testproviderapp,与服务名(application.name)配置不同名。




浙公网安备 33010602011771号