Eureka上集成Spring Cloud 微服务网关 gateway
作者:mmseoamin日期:2023-12-05

系列文章目录

第一章 Java线程池技术应用

第二章 CountDownLatch和Semaphone的应用

第三章 Spring Cloud 简介

第四章 Spring Cloud Netflix 之 Eureka

第五章 Spring Cloud Netflix 之 Ribbon

第六章 Spring Cloud 之 OpenFeign

第七章 Spring Cloud 之 GateWay

Eureka上集成Spring Cloud 微服务网关 gateway,在这里插入图片描述,第1张


文章目录

  • 系列文章目录
  • 前言
  • 1、通过API网关访问服务
  • 2、Spring Cloud GateWay 最主要的功能就是路由转发
  • 3、Gateway的工作流程
  • 4、Predicate 断言
  • 5、示例
    • 5.1、pom.xml配置
    • 5.2、application.xml配置
    • 5.3、启动类
    • 6、动态路由
      • 6.1、修改application.xml配置
      • 7、过滤器Filter
        • 7.1、Filter 分类
          • 7.1.1、GatewayFilter
          • 7.1.2、实例
          • 7.1.2、GlobalFilter
          • 8、总结

            前言

            API 网关是一个搭建在客户端和微服务之间的服务,我们可以在 API 网关中处理一些非业务功能的逻辑,例如权限验证、监控、缓存、请求路由等。

            Eureka上集成Spring Cloud 微服务网关 gateway,在这里插入图片描述,第2张

            基于上一章节的内容,已经集成了Spring Cloud Netflix微服务组件。其中服务发现、注册组件:Eureka,服务远程调用、负载均衡组件:OpenFeign。

            本章节在DNS、Nginx层之后加入网关层,通过Nginx + GateWay 去访问服务。 网关层可以做路由、限流、权限验证、请求过滤等操作。

            Eureka上集成Spring Cloud 微服务网关 gateway,在这里插入图片描述,第3张


            1、通过API网关访问服务

            • 客户端通过 API 网关与微服务交互时,客户端只需要知道 API 网关地址即可,而不需要维护大量的服务地址,简化了客户端的开发。
            • 客户端直接与 API 网关通信,能够减少客户端与各个服务的交互次数。
            • 客户端与后端的服务耦合度降低。
            • 节省流量,提高性能,提升用户体验。
            • API 网关还提供了安全、流控、过滤、缓存、计费以及监控等 API 管理功能。

              2、Spring Cloud GateWay 最主要的功能就是路由转发

              而在定义转发规则时主要涉及了以下三个核心概念,如下表。

              核心概念描述
              Route(路由)网关最基本的模块。它由一个 ID、一个目标 URI、一组断言(Predicate)和一组过滤器(Filter)组成。
              Predicate(断言)路由转发的判断条件,我们可以通过 Predicate 对 HTTP 请求进行匹配,例如请求方式、请求路径、请求头、参数等,如果请求与断言匹配成功,则将请求转发到相应的服务。
              Filter(过滤器)过滤器,我们可以使用它对请求进行拦截和修改,还可以使用它对上文的响应进行再处理。

              3、Gateway的工作流程

              Eureka上集成Spring Cloud 微服务网关 gateway,在这里插入图片描述,第4张

              • 客户端将请求发送到 Spring Cloud Gateway 上。
              • Spring Cloud Gateway 通过 Gateway Handler Mapping 找到与请求相匹配的路由,将其发送给 Gateway Web Handler。
              • Gateway Web Handler 通过指定的过滤器链(Filter Chain),将请求转发到实际的服务节点中,执行业务逻辑返回响应结果。
              • 过滤器之间用虚线分开是因为过滤器可能会在转发请求之前(pre)或之后(post)执行业务逻辑。
              • 过滤器(Filter)可以在请求被转发到服务端前,对请求进行拦截和修改,例如参数校验、权限校验、流量监控、日志输出以及协议转换等。
              • 过滤器可以在响应返回客户端之前,对响应进行拦截和再处理,例如修改响应内容或响应头、日志输出、流量监控等。
              • 响应原路返回给客户端。

                4、Predicate 断言

                pring Cloud Gateway 通过 Predicate 断言来实现 Route 路由的匹配规则。简单点说,Predicate 是路由转发的判断条件,请求只有满足了 Predicate 的条件,才会被转发到指定的服务上进行处理。

                Eureka上集成Spring Cloud 微服务网关 gateway,在这里插入图片描述,第5张

                常见的 Predicate 断言如下表(假设转发的 URI 为 http://localhost:8001)。

                断言示例说明
                Path- Path=/user/listUserInfo/**当请求路径与 /user/listUserInfo/** 匹配时,该请求才能被转发到 http://localhost:8001 上。
                Before- Before=2022-12-07T11:47:34.255+08:00[Asia/Shanghai]在 2022 年 12 月 07 日 11 时 47 分 34.255 秒之前的请求,才会被转发到 http://localhost:8001 上。
                After- After=2022-12-07T11:47:34.255+08:00[Asia/Shanghai]在 2022 年 12 月 07 日 11 时 47 分 34.255 秒之后的请求,才会被转发到 http://localhost:8001 上。
                Between- Between=2022-12-07T15:18:33.226+08:00[Asia/Shanghai],2022-12-07T15:23:33.226+08:00[Asia/Shanghai]在 2022 年 12 月 07 日 15 时 18 分 33.226 秒 到 2022 年 12 月 07 日 15 时 23 分 33.226 秒之间的请求,才会被转发到 http://localhost:8001 服务器上。
                Cookie- Cookie=name,kelvin.com携带 Cookie 且 Cookie 的内容为 name=kelvin.com 的请求,才会被转发到 http://localhost:8001 上。
                Header- Header=X-Request-Id,\d+请求头上携带属性 X-Request-Id 且属性值为整数的请求,才会被转发到 http://localhost:8001 上。
                Method- Method=GET只有 GET 请求才会被转发到 http://localhost:8001 上。

                5、示例

                建立子模块:gateway-service

                5.1、pom.xml配置

                
                
                    4.0.0
                    
                        com.kelvin
                        SpringCloud
                        0.0.1-SNAPSHOT
                    
                    gateway-service
                    
                        8
                        8
                        UTF-8
                    
                    
                        
                            org.springframework.boot
                            spring-boot-starter
                        
                        
                            org.springframework.cloud
                            spring-cloud-starter-netflix-eureka-client
                        
                        
                            org.springframework.cloud
                            spring-cloud-starter-gateway
                        
                    
                
                

                5.2、application.xml配置

                server:
                  port: 80
                spring:
                  application:
                    name: gateway-service
                  cloud:
                    gateway: #网关路由配置
                      routes:
                        #将 drp-user-service 提供的服务隐藏起来,不暴露给客户端,只给客户端暴露 API 网关的地址 80
                        - id: drp-user-service_routh   #路由 id,没有固定规则,但唯一,建议与服务名对应
                          uri: http://localhost:8001          #匹配后提供服务的路由地址
                          predicates:
                            #以下是断言条件,必选全部符合条件
                            - Path=/user/userInfoList/**               #断言,路径匹配 注意:Path 中 P 为大写
                            - Method=GET #只能时 GET 请求时,才能访问
                eureka:
                  instance:
                    instance-id: gateway-service
                    hostname: localhost
                  client:
                    fetch-registry: true
                    register-with-eureka: true
                    service-url:
                      defaultZone: http://localhost:7001/eureka
                

                5.3、启动类

                @SpringBootApplication
                @EnableEurekaClient
                public class GatewayApplication {
                    public static void main(String[] args) {
                        SpringApplication.run(GatewayApplication.class,args);
                    }
                }
                

                访问:http://localhost/user/userInfoList


                6、动态路由

                以服务名(spring.application.name)作为路径创建动态路由进行转发,从而实现动态路由功能

                Route 的 uri 地址修改为以下形式。

                lb://service-name
                

                6.1、修改application.xml配置

                server:
                  port: 80
                spring:
                  application:
                    name: drp-gateway-service
                  cloud:
                    gateway: #网关路由配置
                      routes:
                        #将 drp-user-service 提供的服务隐藏起来,不暴露给客户端,只给客户端暴露 API 网关的地址 80
                        - id: drp-user-service_routh   #路由 id,没有固定规则,但唯一,建议与服务名对应
                          uri: lb://USER-SERVICE          #匹配后提供服务的路由地址
                          predicates:
                            #以下是断言条件,必选全部符合条件
                            - Path=/user/userInfoList/**               #断言,路径匹配 注意:Path 中 P 为大写
                            - Method=GET #只能时 GET 请求时,才能访问
                          metadata:
                             connect-timeout: 10
                             #单位毫秒
                             response-timeout: 10000
                eureka:
                  instance:
                    instance-id: drp-gateway-service
                    hostname: localhost
                  client:
                    fetch-registry: true
                    register-with-eureka: true
                    service-url:
                     defaultZone: http://localhost:7001/eureka
                

                7、过滤器Filter

                用户登陆状态校验、签名校验。

                Spring Cloud Gateway 提供了以下两种类型的过滤器

                过滤器类型说明
                Pre 类型这种过滤器在请求被转发到微服务之前可以对请求进行拦截和修改,例如参数校验、权限校验、流量监控、日志输出以及协议转换等操作。
                Post 类型这种过滤器在微服务对请求做出响应后可以对响应进行拦截和再处理,例如修改响应内容或响应头、日志输出、流量监控等。

                7.1、Filter 分类

                按照作用范围划分,Spring Cloud gateway 的 Filter 可以分为 2 类:GatewayFilter、GlobalFilter

                7.1.1、GatewayFilter

                应用在单个路由或者一组路由上的过滤器。

                常用的GatewayFilter过滤器

                路由过滤器描述参数使用示例
                AddRequestHeader拦截传入的请求,并在请求上添加一个指定的请求头参数。name:需要添加的请求头参数的 key
                value:需要添加的请求头参数的 value。
                - AddRequestHeader=my-request-header,1024
                AddRequestParameter拦截传入的请求,并在请求上添加一个指定的请求参数。name:需要添加的请求参数的 key;
                value:需要添加的请求参数的 value。
                - AddRequestParameter=my-request-param,c.biancheng.net
                AddResponseHeader拦截响应,并在响应上添加一个指定的响应头参数。name:需要添加的响应头的 key;
                value:需要添加的响应头的 value。
                - AddResponseHeader=my-response-header,c.biancheng.net
                PrefixPath拦截传入的请求,并在请求路径增加一个指定的前缀。prefix:需要增加的路径前缀。-PrefixPath=/consumer
                PreserveHostHeader转发请求时,保持客户端的 Host 信息不变,然后将它传递到提供具体服务的微服务中。-PreserveHostHeader
                RemoveRequestHeader移除请求头中指定的参数。name:需要移除的请求头的 key。- RemoveRequestHeader=my-request-header
                RemoveResponseHeader移除响应头中指定的参数。name:需要移除的响应头。- RemoveResponseHeader=my-response-header
                RemoveRequestParameter移除指定的请求参数。name:需要移除的请求参数。- RemoveRequestParameter=my-request-param
                RequestSize配置请求体的大小,当请求体过大时,将会返回 413 Payload Too Large。maxSize:请求体的大小。- name:RequestSize
                   args:
                      maxSize: 5000000

                7.1.2、实例

                spring:
                  application:
                    name: drp-gateway-service
                  cloud:
                    gateway: #网关路由配置
                      routes:
                        #将 drp-user-service 提供的服务隐藏起来,不暴露给客户端,只给客户端暴露 API 网关的地址 80
                        - id: drp-user-service_routh   #路由 id,没有固定规则,但唯一,建议与服务名对应
                          uri: lb://USER-SERVICE          #匹配后提供服务的路由地址
                          predicates:
                            #以下是断言条件,必选全部符合条件
                            - Path=/userInfoList/**               #断言,路径匹配 注意:Path 中 P 为大写
                            - Method=GET #只能时 GET 请求时,才能访问
                          filters:
                            - AddRequestHeader=token
                            - PrefixPath=/user
                

                7.1.2、GlobalFilter

                应用在所有的路由上的过滤器,可用于统一异常处理

                import org.springframework.cloud.gateway.filter.GatewayFilterChain;
                import org.springframework.cloud.gateway.filter.GlobalFilter;
                import org.springframework.core.Ordered;
                import org.springframework.http.HttpHeaders;
                import org.springframework.http.HttpStatus;
                import org.springframework.http.server.RequestPath;
                import org.springframework.http.server.reactive.ServerHttpRequest;
                import org.springframework.http.server.reactive.ServerHttpResponse;
                import org.springframework.stereotype.Component;
                import org.springframework.util.CollectionUtils;
                import org.springframework.web.server.ServerWebExchange;
                import reactor.core.publisher.Mono;
                import java.util.List;
                /***
                 * @title DrfGlobalFilter
                 * @desctption 登录验证
                 * @author kelvin
                 * @create 2023/5/15 14:17
                 **/
                @Component
                public class DrfGlobalFilter implements GlobalFilter, Ordered {
                    @Override
                    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                        ServerHttpRequest request = exchange.getRequest();
                        //获取URI地址
                        RequestPath path = request.getPath();
                        HttpHeaders headers = request.getHeaders();
                        List stringList = headers.get("token");
                        //是否登录验证
                        if(CollectionUtils.isEmpty(stringList)){
                            ServerHttpResponse response = exchange.getResponse();
                            response.setStatusCode(HttpStatus.UNAUTHORIZED);
                            return response.setComplete();
                        }
                        return chain.filter(exchange);
                    }
                    @Override
                    public int getOrder() {
                        //过滤器优先级,0为最高
                        return 0;
                    }
                }
                

                8、总结

                本章节成功的在Spring Cloud Netflix生态上集成了GateWay,基于DNS(域名解析) + Nginx(反向代理) + gateway + Eureka等的微服务架构,能解决安全、路由、限流、请求过滤、流量计费等问题。下一章节我们给大家带来Spring Cloud Netflix框架提供的限流组件Hystrix的功能介绍和使用。