• 微服务架构 | 服务网关 - [Gateway]


    §1 官网与简介

    Zuul
    Gateway
    This project provides a library for building an API Gateway on top of Spring WebFlux. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.

    特性:

    • Built on Spring Framework 5, Project Reactor and Spring Boot 2.0
    • Able to match routes on any request attribute
    • Predicates and filters are specific to routes
    • Circuit Breaker integration
    • Spring Cloud DiscoveryClient integration
    • Easy to write Predicates and Filters
    • Request Rate Limiting
    • Path Rewriting

    对比:

    • 由 Springcloud 团队打造,天然亲和 Springcloud 生态,更新和社区更友好
    • 底层使用 webflux(相比web mvc 非阻塞) 的 reactor-netty 响应式编程组件,zuul 底层是基于 servlet 的阻塞式 I/O,高并发上有优势
    • 整合 Spring5 / project reactor / springboot / websocket 等

    网关在微服务架构中的位置
    在这里插入图片描述

    组成、工作流程和作用
    在这里插入图片描述

    网关由路由、断言、过滤器构成:

    • 断言:起比较作用,可以比较请求的所有部分,比较后匹配的由路由处理
    • 路由:由 ID 、url、断言、过滤器组成,最终由它决定请求交给哪个服务接口处理
    • 过滤:由 spring gateway filter 实例实现,可以在请求前后进行一些操作,比如请求重写
      在这里插入图片描述

    通过上述组件可以实现:

    • 反向代理
    • 鉴权
    • 流量控制
    • 熔断
    • 日志监控
    • 重写

    §2 简单使用(路由)

    依赖

    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-gatewayartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    注意,网关的使用需要 排除 下面两个依赖

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-actuatorartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    配置
    YML 方式

    spring:
      application:
        name: cloud-gateway
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
          routes:
            - id: payment_routh #payment_route    #路由的唯一id
              uri: http://localhost:8001          #服务的路由地址
              predicates:
                - Path=/payment/get/**         # 服务下接口的地址
    		#多个路由如下配置
            - id: payment_routh2 #payment_route
              uri: lb://cloud-payment-service #配置 spring.cloud.gateway.discovery.locator.enabled = true后,可以使用服务名作为服务地址
              predicates:
                - Path=/payment/lb/** 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Configuration 方式

    @Configuration
    public class GatewayRoutelocatorConfig {
        @Bean
        RouteLocator routeLocator(RouteLocatorBuilder builder){
            RouteLocatorBuilder.Builder routes = builder.routes();
            routes.route("n",
                    r->r.path("/").uri("http://www.gamersky.com/"));
            return routes.build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    §3 常用断言

    由 RoutePredicateFactory 实现

    §3.1 path

    Path 路由断言工厂接收一个参数,根据 Path 定义好的规则来判断访问的 URI 是否匹配。

    spring:
      cloud:
        gateway:
          routes:
            - id: host_route
        uri: http://c.biancheng.net
        predicates:
          - Path=/blog/detail/{segment}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果请求路径为 /blog/detail/xxx,则此路由将匹配。也可以使用正则,例如 /blog/detail/** 来匹配 /blog/detail/ 开头的多级 URI。
    path 断言匹配成功后会将断言部分拼接上 uri 作为实际请求路径
    即,若断言为 /a,那实际路径一定是 http://…/a
    示例

    http://localhost:9527/blog/detail/36185 -->
    http://c.biancheng.net/blog/detail/36185

    §3.2 query

    Query 路由断言工厂接收两个参数

    • 一个必需的参数,用于匹配请求中的 query 字段
    • 一个可选的正则表达式,用于匹配请求中的 query 字段的值
    spring:
      cloud:
        gateway:
          routes:
            - id: query_route
          uri: http://c.biancheng.net
          predicates:
            - Query=foo, ba.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    示例

    http://localhost:2001/?foo=baz

    §3.3 method

    Method 路由断言工厂接收一个参数,匹配的是 http 的 method

    spring:
      cloud:
        gateway:
          routes:
            - id: method_route
      uri: http://baidu.com
      predicates:
        - Method=GET
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    §3.4 header

    Header 路由断言工厂接收两个参数

    • 一个必需的参数,用于匹配请求中的请求头名称
    • 一个可选的正则表达式,用于匹配请求中的请求头的值
    spring:
      cloud:
        gateway:
          routes:
            - id: header_route
      uri: http://example.org
      predicates:
        - Header=X-Request-Id, \d+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    §3.5 cookie

    cookie 路由断言工厂接收两个参数

    • 一个必需的参数,用于匹配请求中的 cookie 名
    • 一个可选的正则表达式,用于匹配请求中的 cookie 的值
    spring:
      cloud:
        gateway:
          routes:
            - id: query_route
          uri: http://c.biancheng.net
          predicates:
            - Cookie=chocolate, ch.p
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    §3.6 时间

    时间匹配规定路由路由规则生效的时间范围,有三种模式

    • Before
    • After
    • Between
      时间格式要求为带有时区的时间戳,对应 ZoneDateTime
    spring:
      cloud:
        gateway:
          routes:
            - id: query_route
          uri: http://c.biancheng.net
          predicates:
            - Between=2022-01-20T17:42:47.789-07:00[Asia/Shanghai],2023-01-20T17:42:47.789-07:00[Asia/Shanghai]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    §4 过滤器

    由 GatewayFilterFactroies 实现,原理和 servlet 的 filter 类似。
    filter 分为两类

    • gateway filter
    • global filter

    §4.1 预设过滤器(TODO)

    §4.2 自定义过滤器(TODO)

    加入类扫描,实现默认接口

    • GlobalFilter 全局过滤接口
    • Order 用于指定优先级
      注意 Gateway 的 filter 可以实现拦截器的功能
    @Component
    @Slf4j
    public class TestGlobalFilter implements GlobalFilter, Ordered {
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            log.info("<<>> start");
            String name = exchange.getRequest().getQueryParams().getFirst("name");
            if(StringUtils.isEmpty(name)){
                log.info("<<>> no-name");
                exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
                exchange.getResponse().setComplete();
            }
            return chain.filter(exchange);
        }
    
        @Override
        public int getOrder() {
            return 0;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    本文部分内容来自 Spring Cloud Gateway的常用路由断言工厂


    传送门:
    微服务架构 | 组件目录

  • 相关阅读:
    day01-3-界面显示&用户登录&餐桌状态显示
    【Jmeter】安装配置:Jmeter 安装插件管理器 Plugins Manager
    PySpark
    MyBatisPlus(十二)排序查询:orderBy
    【Linux】虚拟机部署与发布J2EE项目(Windows版本)
    多图看懂Java虚拟机,JVM相关面试常考点全在这里了
    FPGA - 7系列 FPGA SelectIO -08- 高级逻辑资源之OSERDESE2
    STM32与ZigBee技术在智能家居无线通信中的应用研究
    【C3AE】《C3AE:Exploring the Limits of Compact Model for Age Estimation》
    Redis的三种启动方式与检测运行情况
  • 原文地址:https://blog.csdn.net/ZEUS00456/article/details/125778471