Spring Cloud Gateway 原理与应用场景
why 为什么需要网关?如图可知:在常规没有网关的情况下,无法对多个服务进行统一的处理,比如我需要做统一的鉴权,这时候需要在每个服务上增加鉴权功能来达到目的,工作量大且不好维护在有网关的情况下,可以将所有的流量都达到网关,然后通过网关来对请求做统一的鉴权处理,非常方便what 网关的应用场景降低复杂性,如前台请求多个服务,可以通过网关进行简化鉴权(网关中重点):用户是否合法?有哪些权限可以请求哪些
why 为什么需要网关?
如图可知:
- 在常规没有网关的情况下,无法对多个服务进行统一的处理,比如我需要做统一的鉴权,这时候需要在每个服务上增加鉴权功能来达到目的,工作量大且不好维护
- 在有网关的情况下,可以将所有的流量都达到网关,然后通过网关来对请求做统一的鉴权处理,非常方便
what 网关的应用场景
-
降低复杂性,如前台请求多个服务,可以通过网关进行简化
-
鉴权(网关中重点):用户是否合法?有哪些权限可以请求哪些服务
-
安全性:登录态鉴权,如果鉴权不通过,直接被打回去
-
多协议适配,可以针对后端多种不同的协议,在网关层统一处理以后以HTTP对外提供服务,其实就是起到一个适配器的作用
-
限流:网络限流,保证后台服务稳定运行
-
缓存:在网关层统一缓存,如登录态、鉴权信息
-
流量调配:灰度发布(金丝雀发布 / A/B Test),在部署上线新版本的时候,可以通过网关来让部分流量使用新服务,部分流量保持旧服务,有问题可以及时的回滚,让影响面最小
-
统一处理:提供统一的错误码、状态码等
-
请求转发:并且可以基于网关实现内网与外网的隔离
常见网关实现方案对比
Spring Cloud Gateway
- Spring Cloud Gateway是Spring官方团队研发的API网关技术, 它的目的是取代Zuul为微服务提供一个简单高效的API网关。
- Zuul 1.x采用的是传统的thread per connection方式来处理请求,也就是针对每一个请求,会为这个请求专门分配一个线程来进行处理, 直到这个请求完成之后才会释放线程,一旦后台服务器响应较慢,就会使得该线程被阻塞,所以它的性能不好。
- Zuul本身存在的一些性能问题不适合于高并发的场景,虽然后来Netflix决定开发高性能版Zuul 2.x,但是Zuul 2.x的发布时间一直不确定。 虽然Zuul 2.x后来已经发布并且开源了,但是Spring Cloud并没有打算集成进来。
- Spring Cloud Gateway是依赖于Spring Boot 2.0、Spring WebFlux和Project Reactor等技术开发的网关,它不仅提供了统一的路由请求的方式, 还基于过滤链的方式提供了网关最基本的功能。
Zuul
Zuul是Netflix开源的微服务网关
Zuul的核心都是Filter组成,它定义了4中标准的类型过滤器,Pre Filters、Routing Filters、Post Filters、Error Filters,这些会对应请求的整个生命周期
OpenResty
OpenResty本质就是由Nginx+Lua集成的一个高性能Web应用服务器,内部集成了大量Lua库和第三方模块
OpenResty将请求分为多个阶段,可以在不同的阶段挂载Lua脚本来实现不同阶段的自定义行为
OpenResty实现网关功能的核心就是在图中的11个步骤中挂载Lua脚本来实现功能的扩展
网关方案总结
网关 | 限流 | 鉴权 | 监控 | 易用性 | 可维护性 | 成熟度 |
---|---|---|---|---|---|---|
Spring Cloud Gateway | 可以通过ip、用户进行集群限流,提供扩展接口 | 普通鉴权、Auth2.0 | Gateway Metrics Filter | 简单易用 | Spring系列下的,可扩展性高、易配置、可维护性好 | Spring Cloud社区程数,但Gateway资源较少 |
Zuul2.x | 通过配置文件配置对集群限流和单服务限流可通过filter实现限流扩展 | filter中实现 | filter中实现 | 参考资料少 | 可维护性差 | 开源不久,资料少 |
OpenResty | 需使用lua开发实现 | 需使用lua开发实现 | 需要开发 | 简单易用,但需要lua开发的很多 | 可维护性差,将需要维护大量lua库 | 很成熟,资料多 |
Kong | 根据时间单位限流、用户限流,可以在源码上二次开发 | 普通鉴权、Key Auth、HMAC、Auth2.0 | 可上报datadog,记录请求数、请求数据量、应答数据量、接收与发送时间间隔、状态码数量、kong内运行时间 | 简单易用,api转发通过管理员接口配置,开发需使用lua脚本 | 可维护性较差,将需要维护大量lua脚本 | 相对成熟,开源 |
除此之外,还有Tyk、Apisix、Orange
Gateway架构原理
如下图所示:Gateway处理一个请求的过程
- 客户端发起一个请求到gateway
- 通过Netty Server来处理请求
- 【关键】会根据Predicate(谓词)、Filter判断该走哪个路由
- 通过Netty Proxy代理来向微服务发起请求
图中关键点在于 Predicate和Filters,它们都有对应的工厂类
RoutePredicateFactory
RoutePredicateFactory:路由谓词工厂,比如日期、cookie、header、host、predicate、method等属性进行路由
Predicate可以通过HTTP请求的属性进行匹配
- BeforeRoutePredicateFactory——请求在指定日期之前
#【指定时间规则匹配路由】 #在2022-01-01 00:00:00之前访问的请求,都会转到http://localhost:8080,即:http://localhost:8088/say会转发到http://localhost:8080/say spring: cloud: gateway: routes: - id: before_route uri: http://localhost:8080 predicates: - Before=2022-01-01T00:00:00.000+08:00
- AfterRoutePredicateFactory——请求在指定日期之后
#【指定时间规则匹配路由】 #在2021-01-01 00:00:00之后访问的请求,都会转到http://localhost:8080,即:http://localhost:8088/say会转发到http://localhost:8080/say spring: cloud: gateway: routes: - id: after_route uri: http://localhost:8080 predicates: - After=2021-01-01T00:00:00.000+08:00
- CookieRoutePredicateFactory——请求中携带的Cookie是否匹配配置的规则
#【指定Cookie规则匹配路由】 #请求配置localhost的Cookie(chocolate=mic;) 请求http://localhost:8088/say会转发到http://localhost:8080/say spring: cloud: gateway: routes: - id: cookie_route uri: http://localhost:8080 predicates: - Cookie=chocolate, mic
- HeaderRoutePredicateFactory——请求中Header头消息对应的name和value与Predicate配置的值是否匹配
#【指定Header规则匹配路由】 #请求配置Header(key=X-Request-Id value=1) 请求http://localhost:8088/say会转发到http://localhost:8080/say spring: cloud: gateway: routes: - id: header_route uri: http://localhost:8080 predicates: - Header=X-Request-Id, \d+
- HostRoutePredicateFactory——匹配请求中的Host字段进行路由
#【指定Host规则匹配路由】 #请求配置Header(Host:www.muse.com) 请求http://localhost:8088/say会转发到http://localhost:8080/say spring: cloud: gateway: routes: - id: host_route uri: http://localhost:8080 predicates: - Host=**.muse.com
- MethodRoutePredicateFactory——根据HTTP请求的Method属性来匹配以实现路由
#【请求方法匹配路由】 # 请求POST http://localhost:8088/shout会转发http://localhost:8080/shout。请求GET http://localhost:8088/say 会报"404 Not Found" spring: cloud: gateway: routes: - id: method_route uri: http://localhost:8080 #访问地址 predicates: - Method=POST
- PathRoutePredicateFactory——根据请求路径匹配Predicate配置来进行请求路由
#【请求路径匹配路由】 # 请求POST http://localhost:8088/gateway/say会转发http://localhost:8080/say。 spring: cloud: gateway: routes: - id: path_routeHeaderRoutePredicateFactory uri: http://localhost:8080 #访问地址 predicates: - Path=/gateway/** #路径匹配 filters: - StripPrefix=1 #跳过前缀
RouteFilterFactory
RouteFilterFactory:路由过滤器,比如添加reqeust参数、添加header、限流,类似于spring中的fiter
Filter主要分为两种类型:
- Pre类型过滤器
- Post类型过滤器
Filter实现方式主要由两种:
- GatewayFilter只会应用到单个路由或一个分组的路由上
- GlobalFilter会应用到所有的路由上
可用过滤器说明:
- AddRequestParameterGatewayFilterFactory——该过滤器的功能是对所有匹配的request请求中添加一个查询参数
#【添加request查询参数过滤器】 #会对所有请求增加teacher=muse这个参数 spring: cloud: gateway: routes: - id: add_request_parameter_route uri: http://localhost:8080 #访问地址 predicates: - Path=/** filters: - AddRequestParameter=teacher, muse
- AddResponseHeaderGatewayFilterFactory——该过滤器会对所有匹配的请求, 在返回结果给客户端之前, 在Header中添加相应的数据
#【添加response响应Header参数过滤器】 #返回结果给客户端之前,在Header中添加相应的数据 spring: cloud: gateway: routes: - id: add_response_header_route uri: http://localhost:8080 #访问地址 predicates: - Path=/** filters: - AddResponseHeader=X-Response-Teacher, Muse
- RequestRateLimiterGatewayFilterFactory——该过滤器会对访问到当前网关的所有请求执行限流过滤
#【添加限流过滤器】 spring: cloud: gateway: routes: - id: request_ratelimiter_route uri: http://localhost:8080 #访问地址 predicates: - Path=/** filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 1 #令牌桶中令牌的填充速度,代表允许每秒执行的请求数 redis-rate-limiter.burstCapacity: 1 #令牌桶的容量,也就是令牌桶最多能够容纳的令牌数。表示每秒用户最大能够执行的请求数量
- RetryGatewayFilterFactory——请求重试过滤器, 证据指定的触发条件, 发起重试操作
#【添加请求重试过滤器】 spring: cloud: gateway: routes: - id: retry_route uri: http://localhost:8080 predicates: - Path=/example/** filters: - name: Retry args: retries: 3 #请求重试次数,默认值是3 status: 500 #HTTP请求返回的状态码,针对指定状态码进行重试。 - StripPrefix=1
- GatewayMetricsFilter——网关指标过滤器, 这个过滤器会添加name=gateway.requests的timer metrics
#【网关指标过滤器——GatewayMetricsFilter】 management: endpoint: gateway: enabled: true endpoints: web: exposure: include: "*"
- 自定义过滤器——GatewayFilter和GlobalFilter
#【请求路径匹配路由——配置自定义过滤器】 spring: cloud: gateway: routes: - id: define_filter uri: http://localhost:8080 #访问地址 predicates: - Path=/gateway/** #路径匹配 filters: - name: GpDefine #自定义过滤器的名字,即:GpDefineGatewayFilterFactory args: name: Gp_Mic #GpConfig.getName这个值 - StripPrefix=1 #跳过前缀
Gateway集成Nacos实现请求负载
具体实现架构如下图
Gateway集成Sentinel实现网关限流
总结
通过对比多种网关的实现方案,我们可以根据实际业务与各个方案特点进行选型;
重点介绍了Gateway的基本原理,实际应用场景,如鉴权、请求负载、限流等
更多推荐
所有评论(0)