SpringCloud:Gateway服务网关

230 阅读6分钟

Gateway 服务网关

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

1. 为什么需要网关

1.1 网关功能

image-20220525222602496

  1. **网关能用于身份认证和权限校验。**请求来了,首先验证一下你是谁。
  2. **服务路由、负载均衡。**根据用户请求判断将请求发送到对应的微服务;如果有多个微服务负责同一个请求,网关还担任了一个负载均衡的功能。
  3. **请求限流。**当用户请求数超过微服务最大允许请求量,就会由网关负责请求限流。

常常会在网关前添加一个nginx,通过指定的请求路径传到网关,再由网关传至其他微服务。下面就让我们来实现一下网关的服务Gateway

2. gateway快速入门

2.1 搭建网关服务

  1. 创建新的模块

  2. 引入依赖

    <!--网关-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!--nacos服务发现依赖-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    

    因为需要在获取用户请求之后,对其进行路由规则判断,之后需要根据服务路由的对应微服务的服务名称从Nacos注册中心获取服务列表

  3. 配置application.yml,编写请求路由和Nacos地址

    spring:
      cloud:
        gateway:
          routes: # 网关路由配置
            - id: user-service # 路由id,自定义,只要唯一即可,给 gateway 使用
              # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
              uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟对应微服务的服务名称
              predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
                - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
            - id: order-service
              uri: lb://orderservice
              predicates:
                - Path=/order/**
    

image-20220525225107800

【总结】

  • 服务路由是包含一条路由规则,路由规则决定了服务消费者的调用目标,即规定了服务消费者可调用哪些服务提供者。
  • 路由配置包括
    1. 路由id:路由的唯一标识
    2. 路由目标uri:路由的目标地址,http代表固定地址,lb代表根据服务名称负载均衡。目前比较推荐lb
    3. 路由断言predicates:判断路由的规则
    4. 路由过滤器filter:对请求或响应做处理

3. 断言工厂

什么是断言呢?在程序设计中,断言是一种放在程序中的一阶逻辑,目的是为了标示与验证程序开发者预期的结果-当程序运行到断言的位置时,对应的断言应该为真。若断言不为真时,程序会中止运行,并给出错误消息。

我们通过配置文件中向路由配置传入的路由断言字符串,都是由断言工厂Predicate Factory读取并处理,转变为路由判断的条件

我们可以通过在配置文件里设置不同的路由断言来达到不同的效果

名称说明示例
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-Id, \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权重处理

如果想要更多的了解,可以选择官网去查询Spring Cloud Gateway

4. 过滤器工厂

我们接受外部的请求,通过路由转到各个过滤器,可以对请求做各种的处理。例如给当前请求添加或移除一个请求头之类的。

image-20220526224043818

我们可以通过官网去查询Spring Cloud Gateway

image-20220526230846873

4.1 路由过滤器的种类

Spring提供了31种不同的路由过滤器工厂。例如:

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

4.2 路由过滤器

我们通过在配置文件中对应的服务路由设置该路由的过滤器

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://userservice
          predicates:
            - Path=/user/**
          # 过滤器
          filters:
          	# 添加过滤器,给当前请求添加一个请求头
            - AddRequestHeader=test, Test is test

重启服务就可以接受请求头内test的数据Test is test

  • 测试

    1. 网关设置配置

      spring:
        application:
          name: gateway
        cloud:
          nacos:
            server-addr: localhost:8848
          gateway:
            routes: # 网关路由配置
              - id: user-service # 路由id,自定义,只要唯一即可,给 gateway 使用
                # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
                uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟对应微服务的服务名称
                predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
                  - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
                filters:
                  - AddRequestHeader=test, Test is test
      
    2. userservicecontroller层进行测试

      通过@RequestHeader获取请求头内容。如果请求头内容缺失会直接报错400

      public class UserController {
          /**
           * 路径: /user/110
           *
           * @param id 用户id
           * @return 用户
           */
          @GetMapping("/{id}")
          public User queryById(@PathVariable("id") Long id,@RequestHeader(value = "Test",required = true) String test) {
              System.out.println(test);
              return userService.queryById(id);
          }
          
          ...
      }
      
    3. 如果在控制台看见 Test is test成功打印说明路由过滤器生效。

4.3 默认过滤器

当我们有大量的服务路由,想要给它们同时实现添加过滤器,可以使用默认过滤器。默认过滤器是通过修改配置完成。

使用默认过滤器可以给所有的路由添加过滤器。对所有的路由都生效。通过default-filters来配置。

spring:
  cloud:
    gateway:
      default-filters:
        - AddRequestHeader=test, Test is test
  • 测试

    1. 网关设置配置

      spring:
        application:
          name: gateway
        cloud:
          nacos:
            server-addr: localhost:8848
          gateway:
            routes: # 网关路由配置
              - id: user-service # 路由id,自定义,只要唯一即可,给 gateway 使用
                # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
                uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟对应微服务的服务名称
                predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
                  - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
            default-filters:
              - AddRequestHeader=test, Test is test
      
    2. userservicecontroller层进行测试

      public class UserController {
          /**
           * 路径: /user/110
           *
           * @param id 用户id
           * @return 用户
           */
          @GetMapping("/{id}")
          public User queryById(@PathVariable("id") Long id,@RequestHeader(value = "Test",required = true) String test) {
              System.out.println(test);
              return userService.queryById(id);
          }
          
          ...
      }
      
    3. 如果在控制台看见 Test is test成功打印说明默认过滤器生效。