gateway 组件是SpringCloud 组件中的网关组件,主要是解决路由转发的问题;跟nginx有点类似,区别是nginx多用在前端上,gateway用在后端上。当然gateway的功能不止路由转发,还可以用来:
1.针对所有请求做统一鉴权、限流、熔断、日志;
2.协议转化,针对后端多种协议可以在网关层统一处理后以http对外服务;
3.统一错误代码处理(跟springboot统一错误处理配置一样);
gateway的配置文件是其使用的核心。
spring:
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- Path=/table-service/**
filters:
- StripPrefix=1
字段说明:
id:自定义路由的ID;
uri:目标服务器地址,同时支持 URI(http://ip:port/route) 和 lb(lb://应用注册服务名) 方式,推荐使用lb方式;
predicates:路由条件,根据匹配结果决定是否执行该请求路由;
filters:过滤规则,包含 pre 和 post 过滤,其中 StripPrefix=1 表示根据请求时去掉URL路径的第一个前缀。
即 predicates 配置项,支持多种规则:
时间的书写必须是ZoneDateTime格式。
spring:
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- After=2022-07-20T10:25:00.000+08:00[Asia/Shanghai]
有三种规则:
After:指定时间之后转发到该服务;
Before:指定时间之前转发到该服务;
Between:两个时间之前转发到该服务,两个时间之间用逗号隔开;
spring:
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- Cookie=cho,123
上述配置表示请求时 Cookie 必须携带 cho=123 键值对才能转发到该服务;逗号前表示键值,逗号后表示该键对应的值,该值是个正则表达式。
spring:
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- Header=cho,123
上述配置表示请求时 header 必须携带 cho=123 键值对才能转发到该服务;逗号前表示键值,逗号后表示该键对应的值,该值是个正则表达式。
spring:
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- Host=127.0.0.1,localhost
上述配置表示请求时 Host 必须携带 127.0.0.1,localhost 中的任何一个值才能转发到该服务;匹配多值时用逗号隔开,并且支持星号(*)做域名通配符。
spring:
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- Method=POST,GET
上述配置表示请求时只有 GET 和 POST 方法才能转发到该服务;匹配多值时用逗号隔开。
spring:
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- Path=/table/**
该方式是使用最多的。/* 表示单层路径匹配,/** 表示多层路径匹配。
即 filters 配置项,支持多种配置:
spring:
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- Path=/table/**
filters:
- AddRequestParameter=foo,bar
上述配置会对走该路由的所有请求都加上 foo=bar 参数。
spring:
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- Path=/table/**
filters:
- AddResponseHeader=foo,bar
上述配置会对走该路由的所有请求的返回都加上响应头 foo=bar 。
spring:
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- Path=/table/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
这个过滤器是基于令牌桶实现的,replenishRate 表示令牌填充速度,burstCapacity 表示令牌桶容量;限流用的,需要集成redis才行。限流的使用略复杂,建议单独研究。
spring:
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- Path=/table/**
filters:
- name: Retry
args:
retries: 3
status: 503
总共涉及4个参数:
retries:重试次数;
status:http 请求返回的状态码,上述配置表示服务端返回503时发起重试;
methods:指定请求类型才会发起重试;
series:配置错误码段,表示符合状态码才发起重试,默认SERVER_ERROR(5),即 5xx 段状态码才会发起重试;如果 series 配置了错误码,但 status 缺省,则仍然匹配 series 进行重试。
自定义 filter 有两个,GlobalFilter 和 GatewayFilter ;GlobalFilter 对全局生效,GatewayFilter 只对配置了的才生效。
可以存在多个 GlobalFilter,执行顺序由 getOrder() 控制,值越小执行越靠前。
@Slf4j
@Service
public class GatewayGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("pre action..."); //请求到路由前的操作...
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("post action..."); //请求返回后的操作...
}));
}
@Override
public int getOrder() {
return 0;
}
}
@Slf4j
@Service
public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory {
public CustomGatewayFilterFactory() {
super(CustomConfig.class);
}
@Override
public GatewayFilter apply(CustomConfig config) {
return ((exchange, chain) -> {
String name = config.getName();
log.info("config name:{}", name);
log.info("pre action...");
if (name.equals("123")) { // 使用config值的样例
return exchange.getResponse().setComplete(); // 不返回任何信息
}
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("post action...");
}));
});
}
public static class CustomConfig {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
上述对应的配置文件:
spring:
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- Path=/table/**
filters:
- name: Custom
args:
name: 123
几点注意:
1. 类名一般遵循以 GatewayFilterFactory 结尾,所以默认情况下过滤器 name 会采用该自定义类名的前缀,这里配置 name=Custom;或者类名完全不遵循上述规则,,配置时name为类全名;
2. 在 apply 方法中,同时包含 Pre 和 Post 过滤;在 then 方法中是请求执行结束之后的处置;
3. CustomConfig 是一个配置类,其属性值可在配置文件 args 下一层进行配置;
以下是请求不满足条件时的 json 返回。
// msg 是个 json 字符串
DataBuffer bodyDataBuffer =response.bufferFactory().wrap(msg.getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(bodyDataBuffer));
端口:9099
本片代码不是该博客核心,忽略。
依赖:
4.0.0
org.example
eureka-gateway
1.0.0
org.springframework.boot
spring-boot-starter-parent
2.4.5
org.springframework.cloud
spring-cloud-starter-gateway
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.projectlombok
lombok
org.springframework.cloud
spring-cloud-dependencies
2020.0.2
pom
import
启动类:
@EnableEurekaClient
@SpringBootApplication
public class GatewayServer {
public static void main(String[] args) {
SpringApplication.run(GatewayServer.class, args);
}
}
配置文件:
server:
port: 8999
spring:
application:
name: gateway-service
cloud:
gateway:
routes:
- id: table-service
uri: lb://table-service
predicates:
- Path=/table-service/**
filters:
- StripPrefix=1
- id: table-service
uri: lb:ws://table-service #这是websocket转发的配置
predicates:
- Path=/table-socket/**
filters:
- StripPrefix=1
eureka:
instance:
lease-expiration-duration-in-seconds: 10
lease-renewal-interval-in-seconds: 5
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
client:
service-url:
defaultZone: http://user:passwd@localhost:9099/eureka/