• 微服务网关:Spring Cloud Zuul 升级 Spring Cloud Gateway 的核心要点


    1. 服务路由

    1.1. Zuul 接收请求:

    1. 在routes路由规则中,根据path去匹配,如果匹配中,就使用对应的路由规则进行请求转发
    2. 如果无法从routes中匹配,则根据path用“/”去截取第一段作为服务名进行请求转发,转发时,默认将第一段截取调
    3. 如果截取的服务名不在注册中心中存在服务,则报错404

    1.2. Gateway 接收请求:

    1. 在routes路由规则中,根据断言(predicates)来匹配路由规则,最常用的是Path;在 zuul 中,会提供默认的 url 截取,在 Gateway 这里,需要我们主动使用 StripPrefix 过滤器来完成
    2. 如果从routes路由中,经过断言也无法匹配,则直接返回404

    所以这里需要注意,如果在zuul网关有服务使用了路由转发但是没有配置,在gateway这里一定要手动配置上。

    2. 过滤器

    在使用 Zuul 网关中,常使用 javax.servlet.Filtercom.netflix.zuul.ZuulFilter来完成过滤器的作用。

    如果改造为 Spring cloud Gateway,可使用 org.springframework.web.server.WebFilterorg.springframework.cloud.gateway.filter.GlobalFilter来完成替换。

    其中 WebFilter 对应 Filter,是对路由转发+web接口调用进行过滤;而网关组件提供的过滤器,如 ZuulFilter 和 GlobaFilter,只针对路由转发进行过滤。

    业务逻辑全链路异步非阻塞:
    在 Spring cloud Gateway 中使用 WebFilter 和 GlobaFilter 进行过滤,所有业务逻辑和方法调用,都不能是同步阻塞的,一定得保证整个调用链路都是异步非阻塞的,否则执行会报错,因为高版本 WebFlux 中,会检测链路是否为异步非阻塞。

    3. 异步非阻塞的中间件

    3.1. 服务调用

    因为在 Zuul 网关中,微服务的调用一般使用 Spring Cloud Openfeign 完成的,而这个组件底层是使用 HttpClient、OkHttp等 HTTP 组件来完成接口调用,是同步阻塞的;因此,我们需要改造为异步非阻塞,这里我们将使用 Webflux 提供的 WebClient 来完成。将每个微服务的 Openfeign 调用重新封装为对应的 WebClient 客户端,用于支撑异步非阻塞的 HTTP 接口调用。
    因为 Spring Cloud Gateway 是基于 Spring Webflux 构造的,因为我们不需要再单独引入 Spring Webflux 依赖。

    下面给一个创建 WebClient 实例的代码:
    有一个注意点:需要给 WebClient 添加负载均衡的过滤器。

    @Autowired
    private LoadBalancedExchangeFilterFunction lbFunction;
    
    /**
     * 创建webClient实例
     * @param webClientName 客户端名称
     * @param webClientInstanceProperties 客户端配置
     * @return webClient实例
     */
    private WebClient createWebClient(String webClientName, WebClientInstanceProperties webClientInstanceProperties) {
    
        UnaryOperator<HttpClient> mapper = client -> {
            client.compress(true)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, webClientInstanceProperties.getConnectTimeout());
            return client;
        };
        ReactorResourceFactory reactorResourceFactory = new ReactorResourceFactory();
        reactorResourceFactory.setLoopResources(LoopResources
                .create(webClientName + "-webclient-http-loop", webClientInstanceProperties.getSelectCount(), webClientInstanceProperties.getWorkerCount(), true));
        reactorResourceFactory.setConnectionProvider(ConnectionProvider.builder(webClientName + "-webclient-http-channel")
                .maxConnections(webClientInstanceProperties.getMaxConnections()).pendingAcquireTimeout(Duration.of(webClientInstanceProperties.getAcquireTimeout(), ChronoUnit.MILLIS)).build());
        return WebClient.builder()
                .clientConnector(new ReactorClientHttpConnector(reactorResourceFactory, mapper))
                .filter(lbFunction)
                .build();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    因为我们可能会存在多个服务调用,因此可做成可配置化。
    在这里插入图片描述
    在这里插入图片描述

    3.2. 数据库

    Zuul 网关,主要使用的数据库中间件有:MySQL、MongoDB 和 Redis。

    3.2.1. 异步非阻塞MySQL

    MySQL 我们可以使用 Spring Boot 提供的 spring-boot-starter-data-r2dbc

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-r2dbcartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    调用 MySQL 使用上述组件提供的ReactiveCrudRepository即可。

    3.2.2. 异步非阻塞MongoDB

    MondoDB 我们可以使用 Spring Boot 提供的 spring-boot-starter-data-mongodb-reactive

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-mongodb-reactiveartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    调用 MongoDB 使用上述组件提供的ReactiveMongoTemplateMongoClient即可

    3.2.3. 异步非阻塞Redis

    Redis 我们可以使用 Spring Boot 提供的 spring-boot-starter-data-redis-reactive

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-redis-reactiveartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    调用 Redis 使用上述组件提供的ReactiveRedisTemplate即可。

  • 相关阅读:
    中国石油大学《高等数学二》第三次在线作业
    word2vec包中cbow模型--学习笔记
    SpringBoot+Vue“咱村那些事”乡村基层信息采集系统
    LLVM(6)ORC实例分析:Transform in cpp
    Java 如何经行异常处理?常见的运行异常的编译时异常
    Docker容器实现MySQL主从复制
    Java面向对象07:简答小结类与对象
    Android 12.0 Launcher3定制化功能之抽屉式(双层)app列表排序功能实现
    (计算机组成原理)第五章中央处理器-第七节2:硬件多线程的基本概念
    hcia 目的mac为(单播 组播 广播)mac
  • 原文地址:https://blog.csdn.net/Howinfun/article/details/133563415