image

SpringCloudGateway

什么是网关


网关:就是网络的关口,负责请求的路由、转发、身份校验。

image

image

SpringCloudGateway快速入门


流程如下:

  1. 创建新模块

image

  1. 引入网关依赖
<!--网关-->  
<dependency>  
    <groupId>org.springframework.cloud</groupId>  
    <artifactId>spring-cloud-starter-gateway</artifactId>  
</dependency>  
<!--nacos discovery-->  
<dependency>  
    <groupId>com.alibaba.cloud</groupId>  
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>  
</dependency>  
<!--负载均衡-->  
<dependency>  
    <groupId>org.springframework.cloud</groupId>  
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>  
</dependency>
  1. 其他模块引入依赖
<!--nacos discovery-->  
<dependency>  
    <groupId>com.alibaba.cloud</groupId>  
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>  
</dependency>  
  1. 编写启动类
@SpringBootApplication  
public class GateWayApplication {  
    public static void main(String[] args) {  
        SpringApplication.run(GateWayApplication.class, args);  
    }  
}
  1. 配置路由规则

application.yaml

server:  
  port: 8080  
spring:  
  application:  
    name: gateway  
  cloud:  
    nacos:  
      discovery:  
        server-addr: 127.0.0.1:8848  
    gateway:  
      routes:  
        - id: item # 路由规则id,自定义,唯一  
          uri: lb://item-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉去服务  
          predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由导目标服务  
            - Path=/items/**,/search/** # 请求路径作为判断条件  
        - id: cart # 路由规则id,自定义,唯一  
          uri: lb://cart-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉去服务  
          predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由导目标服务  
            - Path=/carts/** # 请求路径作为判断条件  
        - id: user # 路由规则id,自定义,唯一  
          uri: lb://user-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉去服务  
          predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由导目标服务  
            - Path=/users/**,/address/** # 请求路径作为判断条件  
        - id: trade  
          uri: lb://trade-service  
          predicates:  
            - Path=/orders/**  
        - id: pay  
          uri: lb://pay-service  
          predicates:  
            - Path=/pay-orders/**

注意:

其他模块中也需要配置application.yml,如下:

spring:
  application:
    name: yupao-user # 这个一定要和你的路由规则能匹配上
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

如果你的gateway模块或多或少基础父项的springweb依赖,可以参考以下设置:

spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
      - org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
      - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
  main:
    web-application-type: reactive

以及,如果出现CORS[^1],可以使用 webflux 版的cors配置:

server:
	baseURL: http://xxx.com

spring:
	gateway:
		globalcors:
        	cors-configurations:
	          '[/**]':
	            allowedOriginPatterns:
	              - "${server.baseURL}"
	            allowedMethods:
	              - "*"
	            allowedHeaders:
	              - "*"
	            allowCredentials: true

路由属性


网关路由对应的Java类型是RouteDefinition,其中常见的属性有:

  • id:路由唯一标示
  • uri:路由目标地址
  • predicates:路由断言,判断请求是否符合当前路由
  • filters:路由过滤器,对请求或响应做特殊处理

路由断言

Spring 提供了12种基本的RoutePredicateFactory实现:

名称说明示例
After是某个时间点后的请求- After=2037-01-20T17:42
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权重处理- Weight=group1, 2
XForwarded Remote Addr基于请求的来源IP做判断- XForwardedRemoteAddr=192.168.1.1/24

路由过滤器

网关中提供了33种路由过滤器,每种过滤器都有独特的作用。

名称说明示例
AddRequestHeader给当前请求添加一个请求头AddrequestHeader=headerName,headerValue
RemoveRequestHeader移除请求中的一个请求头RemoveRequestHeader=headerName
AddResponseHeader给响应结果中添加一个响应头AddResponseHeader=headerName,headerValue
RemoveResponseHeader从响应结果中移除有一个响应头RemoveResponseHeader=headerName
RewritePath请求路径重写RewritePath=/red/?(?<segment>.*), /$\{segment}
StripPrefix去除请求路径中的N段前缀StripPrefix=1,则路径/a/b转发时只保留/b
...
自定义过滤器

网关过滤器有两种,分别是:

  • GatewayFilter:路由过滤器,作用于任意指定的路由;默认不生效,要配置到路由后生效
  • GlobalFilter:全局过滤器,作用范围是所有路由;声明后自动生效

两种过滤器的过滤方法签名完全一致:

image

image

自定义过滤器GlobalFilter
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // TODO 模拟登录校验逻辑
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();
        System.out.println("headers= " + headers);
        // 放行
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}