• 微服务与中间件——GateWay网关


    GateWay

    SpringCloudGateway则是 基于Spring5中提供的WebFlux,属于响应
    式编程的实现,具备更好的性能

    为什么需要网关

    1. 进行身份验证、权限校验
    2. 进行服务路由、负载均衡
    3. 请求限流

    QuickStart

    准备工作

    该项目依赖nacos+feign,这两个配好是前提条件,若有问题请查看:微服务与中间件系列——Feign

    1.构建一个新服务

    在这里插入图片描述

    2.引入依赖

    注意一定要加上loadBalanced依赖,因为新版本中已经去除了Ribbon的负载所以我们要引入
    否则会有There was an unexpected error (type=Service Unavailable, status=503)报错提示

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.修改yaml

    server:
      port: 8899
    spring:
      application:
        name: gateway
      cloud:
        nacos:
          server-addr: localhost:8848
        gateway:
          routes: # 网关路由配置
            - id: test-service # 自定义路由id,必须唯一
              uri: lb://userService # 路由的目标地址,lb表示loadbalance负载均衡,后://服务名
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.启动类加上@EnableDiscoveryClient注解

    GateWay的流程

    在这里插入图片描述

    路由断言工厂(Route Predicate Factory)

    网关路由可以配置的内容包括:

    1. 路由id:路由唯一标示
    2. uri:路由目的地,支持lb和http两种
    3. predicates:路由断言,判断请求是否符合要求,符合则转发到路由目的
    4. filters:路由过滤器,处理请求或响应

    我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件

    例如Path=/user/**是按照路径匹配,这个规则是由
    org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的

    11种基本的断言工厂

    名称说明示例
    After是某个时间点后的请求- After=2037-01-20T17:42:47.789-07:00[America/Denver]
    Before是某个时间点之前的请求- Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
    Between是某两个时间点之前的请求-Between=2037-01-20T17:42:47.789-07:00[America/Denver],
    2037-01-21T17:42:47.789-07:00[America/ Denver]
    cookie请求必须包含某些cookie- Cookie=chocolate, ch.p
    Header请求必须包含某些header- Header=X-Request-ld,\d+
    Host请求必须是访问某个host(域名)- Host=.somehost.org,.anotherhost.org
    Method请求方式必须是指定方式- Method=GET,POST
    Path请求路径必须符合指定规则- Path=/red/{segment},/ blue/**
    Query请求参数必须包含指定参数- Query=name,Jack或者-Query=name
    RemoteAddr请求者的ip必须是指定范围- RemoteAddr=192.168.1.1/24
    weight权重处理

    路由过滤器

    1. 对路由的请求或响应做加工处理,比如添加请求头
    2. 配置在路由下的过滤器只对当前路由的请求生效

    常用过滤器

    名称说明
    AddRequestHeader给当前请求添加一个请求头
    RemoveRequestHeader移除请求中的一个请求头
    AddResponseHeader给响应结果中添加一个响应头
    RemoveResponseHeader从响应结果中移除有一个响应头
    RequestRateLimiter限制请求的流量

    使用

    修改yaml配置文件

    filters: #过滤器
       - AddResponseHeader: Name , value # 给响应结果中添加一个响应头
    
    • 1
    • 2

    完整配置

    server:
      port: 13000
    spring:
      application:
        name: GateWayServer
      cloud:
        nacos:
          server-addr: 192.168.31.149:8848
        gateway:
          routes: #网关路由配置
            - id: router-we
              uri: lb://RouterWe
              predicates:
                - Path=/test/**
              filters: #过滤器
                - AddResponseHeader: Name , value # 给响应结果中添加一个响应头
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    请求头

    若你添加的是请求头,你可以借助@RequestHeader注解进行获取

    filters:
    	- AddRequestHeader: test , zhangsan
    
    • 1
    • 2

    在接口中使用

    @RequestHeader(value="test")
    
    • 1

    添加默认全局过滤器(default-filters)

    注意位置,是和routes一个层级的!
    在这里插入图片描述

    default-filters:#默认过滤器,会对所有的路由请求都生效
    	- AddRequestHeader= defaultAll , testAll #添加请求头
    
    • 1
    • 2

    添加全局过滤器(GlobalFilter)

    全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。
    区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。定义方式是实现GlobalFilter接口。
    在这里插入图片描述

    使用

    这里我们进行模拟用户认证拦截

    1.定义Filter实现GlobalFilter接口
    public class AuthorizeFilter implements GlobalFilter {}
    
    • 1
    2.增加@Component注解注册为组件
    @Component
    public class AuthorizeFilter implements GlobalFilter {}
    
    • 1
    • 2
    3.增加@Order注解设置顺序
    @Order(-1)
    @Component
    public class AuthorizeFilter implements GlobalFilter {}
    
    • 1
    • 2
    • 3
    4.实现逻辑
     @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            //获取请求参数
            final ServerHttpRequest request = exchange.getRequest();
            final MultiValueMap<String, String> queryParams = request.getQueryParams();
            //获取authorization参数
            final String auth = queryParams.getFirst("authorization");
            //判断参数值
            if ("admin".equals(auth)){
                //放行
                return chain.filter(exchange);
            }
            //拦截并返回相应信息
            final ServerHttpResponse response = exchange.getResponse();
            //提示用户未认证
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            //拦截请求
            return exchange.getResponse().setComplete();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    完整代码
    /**
     * 全局认证过滤器
     */
    @Order(-1)
    @Component
    public class AuthorizeFilter implements GlobalFilter {
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            //获取请求参数
            final ServerHttpRequest request = exchange.getRequest();
            final MultiValueMap<String, String> queryParams = request.getQueryParams();
            //获取authorization参数
            final String auth = queryParams.getFirst("authorization");
            //判断参数值
            if ("admin".equals(auth)){
                //放行
                return chain.filter(exchange);
            }
            //拦截并返回相应信息
            final ServerHttpResponse response = exchange.getResponse();
            //提示用户未认证
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            //拦截请求
            return exchange.getResponse().setComplete();
        }
    }
    
    • 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
    • 27
    测试访问

    由于我们的逻辑就是获取访问参数的方式,所以当我们测试访问时就需要加上参数:?authorization=admin,否则报401错误(未认证用户访问)

    实际业务中多是判断请求头中是否含有token进行身份认证!

    过滤器顺序

    请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter
    请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器

    • 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前
    • GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定
    • 路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增
    • 当过滤器的order值一样时,会按照defaultFilter >路由过滤器>GlobalFilter的顺序执行。

    在这里插入图片描述

    CORS跨域

    官网:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#cors-configuration

    你能配置的参数有哪些?

    在这里插入图片描述

    示例

        gateway:
          routes: #网关路由配置
            - id: router-we
              uri: lb://RouterWe
              predicates:
                - Path=/test/**
              filters: #过滤器
                - AddResponseHeader: this is the header # 给响应结果中添加一个响应头
          globalcors: # 全局跨域处理
            cors-configurations:
              '[/**]':
                allowedOrigins: # 允许哪些网站进行跨域请求
                  - "http://localhost:8080"
                allowedMethods:
                  - "GET"
                  - "POST"
                  - "DELETE"
                  - "PUT"
                  - "OPTIONS"
                allowedHeaders: "*" # 允许所有请求头
                allowCredentials: true # 是否允许携带cookie
                maxAge: 360000 # 跨域监测有效期
            add-to-simple-url-handler-mapping: true #解决options请求拦截
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    allowedMethods

    根据官网给出的示例,你也可以不加引号直接写

     allowedMethods:
       - GET
    
    • 1
    • 2
  • 相关阅读:
    华科重要实验
    Unity 3D 碰撞体(Collider)|| Unity 3D 触发器(Trigger)
    Vue入门(二)
    认识ARP协议
    jquery监听滚动条,实现“返回顶部”
    C++ 运算符重载
    在Ubuntu 18.04上支持C++17的std::filesystem的方法
    抑郁了怎么办?改变抑郁情绪的几个建议
    [Python进阶] Pyinstaller打包程序时为程序添加图标
    使用SqlSessionFactory工具类抽取
  • 原文地址:https://blog.csdn.net/qq_51553982/article/details/126510638