why 为什么需要网关?

在这里插入图片描述
如图可知:

  • 在常规没有网关的情况下,无法对多个服务进行统一的处理,比如我需要做统一的鉴权,这时候需要在每个服务上增加鉴权功能来达到目的,工作量大且不好维护
  • 在有网关的情况下,可以将所有的流量都达到网关,然后通过网关来对请求做统一的鉴权处理,非常方便

what 网关的应用场景

  1. 降低复杂性,如前台请求多个服务,可以通过网关进行简化

  2. 鉴权(网关中重点):用户是否合法?有哪些权限可以请求哪些服务在这里插入图片描述

  3. 安全性:登录态鉴权,如果鉴权不通过,直接被打回去

  4. 多协议适配,可以针对后端多种不同的协议,在网关层统一处理以后以HTTP对外提供服务,其实就是起到一个适配器的作用

  5. 限流:网络限流,保证后台服务稳定运行

  6. 缓存:在网关层统一缓存,如登录态、鉴权信息

  7. 流量调配:灰度发布(金丝雀发布 / A/B Test),在部署上线新版本的时候,可以通过网关来让部分流量使用新服务,部分流量保持旧服务,有问题可以及时的回滚,让影响面最小在这里插入图片描述

  8. 统一处理:提供统一的错误码、状态码等

  9. 请求转发:并且可以基于网关实现内网与外网的隔离

常见网关实现方案对比

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.0Spring WebFluxProject Reactor等技术开发的网关,它不仅提供了统一的路由请求的方式, 还基于过滤链的方式提供了网关最基本的功能。

Zuul

Zuul是Netflix开源的微服务网关
在这里插入图片描述
Zuul的核心都是Filter组成,它定义了4中标准的类型过滤器,Pre FiltersRouting FiltersPost FiltersError Filters,这些会对应请求的整个生命周期

OpenResty

OpenResty本质就是由Nginx+Lua集成的一个高性能Web应用服务器,内部集成了大量Lua库和第三方模块
在这里插入图片描述
OpenResty将请求分为多个阶段,可以在不同的阶段挂载Lua脚本来实现不同阶段的自定义行为
OpenResty实现网关功能的核心就是在图中的11个步骤中挂载Lua脚本来实现功能的扩展

网关方案总结

网关限流鉴权监控易用性可维护性成熟度
Spring Cloud Gateway可以通过ip、用户进行集群限流,提供扩展接口普通鉴权、Auth2.0Gateway 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处理一个请求的过程
在这里插入图片描述

  1. 客户端发起一个请求到gateway
  2. 通过Netty Server来处理请求
  3. 【关键】会根据Predicate(谓词)、Filter判断该走哪个路由
  4. 通过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主要分为两种类型:

  1. Pre类型过滤器
  2. Post类型过滤器

Filter实现方式主要由两种:

  1. GatewayFilter只会应用到单个路由或一个分组的路由上
  2. 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的基本原理,实际应用场景,如鉴权、请求负载、限流等

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐