Gateway是在Spring生态系统之上构建的API网关服务,旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,基于WebFlux框架实现,而WebFlux框架底层又使用了高性能的Reactor模式通信框架Netty。常用功能有反向代理、鉴权、流量控制、熔断和日志监控
Route(路由)
是构建网关的基本模块,由ID、目标URI、一系列断言和过滤器组成,断言为true时匹配该路由
Predicate(断言)
请求与断言相匹配则进行路由
Filter(过滤)
可以在请求被路由前或之后对请求进行修改
流程图如下
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
server:
port: 8812
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: provider_routh
uri: http://localhost:8770
predicates:
- Path=/provider/getProviderInfo/**
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
依次启动Eureka Server、Provider和Gateway三个微服务,在浏览器输入地址http://localhost:8812/provider/getProviderInfo/world
新建一个GatewayConfig类
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
RouteLocatorBuilder.Builder routes = builder.routes();
routes.route("provider_routh", predicate -> predicate.path("/provider/getProviderConfigInfo/**")
.uri("http://localhost:8770")).build();
return routes.build();
}
}
再次启动Gateway服务,在浏览器地址输入http://localhost:8812/provider/getProviderConfigInfo/zhangsan就可以直接跳转到百度新闻网
默认情况下Gateway会根据注册中心注册的服务列表, 以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- Path=/provider/getProviderInfo/**
在浏览器地址栏输入http://localhost:8812/provider/getProviderInfo/zhangsan
Spring Cloud Gateway包括许多内置的Route Predicate工厂,所有这些Predicate都与HTTP请求的不同属性匹配,多个Route Predicate工厂可以进行组合,常见的如下:
指定日期(ZonedDateTime)之后才能访问请求路径
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- After=2022-09-07T17:42:47.789+08:00[Asia/Shanghai]
指定日期(ZonedDateTime)之前才能访问请求路径
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- Before=2022-09-08T17:42:47.789+08:00[Asia/Shanghai]
指定日期(ZonedDateTime)之间才能访问请求路径
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- Between=2022-09-07T17:42:47.789+08:00[Asia/Shanghai], 2022-09-08T17:42:47.789+08:00[Asia/Shanghai]
通过获取对应的 Cookie name 值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- Cookie=username, zhangsan
请求中必须带有消息头,且要匹配名称和值
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- Header=X-Request-Id, \d+
一组匹配的域名列表,用.号作为分隔符,通过参数中的主机地址作为匹配规则
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- Host=**.xlhj.org,**.xlhj.com
HTTP请求方式进行匹配POST/GET
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- Method=GET,POST
请求路径进行匹配
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- Path=/provider/getProviderInfo/**
查询条件匹配,一个参数时,表示请求参数中必须包含此值;两个参数时,表示请求参数中包含此值,参数值匹配第二个参数
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- Query=username, zhangsan
IP地址进行匹配
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- RemoteAddr=192.168.1.1/24
权重进行匹配
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- Weight=group1, 2
- id: order_routh
uri: http://localhost:8770
predicates:
- Weight=group1, 8
20%请求走上面服务,80%请求走下面服务
用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用,主要有两类,即GatewayFilter和GlobalFilter
AddRequestHeader:请求头过滤器
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- Path=/provider/getProviderInfo/**
filters:
- AddRequestHeader=X-Request-Id, xlhj
AddRequestParameter:请求参数过滤器
spring:
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: provider_routh
uri: lb://CLOUD-PROVIDER #匹配后提供服务的路由地址
predicates:
- Path=/provider/getProviderInfo/**
filters:
- AddRequestParameter=X-Request-Id, xlhj
其他过滤器用法都差不多
自定义全局过滤器需要实现GlobalFilter和Ordered两个接口,常用语全局日志记录和统一权限认证,新建一个GatewayGlobalFilter类,代码如下:
@Component
public class GatewayGlobalFilter implements GlobalFilter, Ordered {
private static final Logger logger = LoggerFactory.getLogger(GatewayGlobalFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
logger.info("执行自定义全局过滤器");
String requestId = exchange.getRequest().getQueryParams().getFirst("X-Request-Id");
if (StringUtils.isBlank(requestId)) {
logger.info("请求参数为空!");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
重新启动gateway微服务,浏览器地址栏输入http://localhost:8812/provider/getProviderInfo/world?X-Request-Id=xlhj