SpringCloud之gateway
简介
Gateway(网关)是一种用于构建微服务架构的重要组件,它充当了系统的入口点,将外部请求转发到相应的微服务中。
- 路由转发:Gateway 扮演着请求转发的角色,根据请求的路径和规则将请求转发到相应的微服务实例上。它可以对请求进行动态路由、负载均衡、熔断处理等。
- 安全与认证:Gateway 可以集成认证和授权机制,例如 OAuth、JWT 等,用于保护微服务的安全性。它可以拦截请求并验证用户身份、权限等。
- 流量控制:Gateway 可以通过限流和配额设置来控制流量,防止过多的请求超过各个微服务的处理能力。它可以根据服务实例的负载情况进行智能的流量分发和控制。
- 协议转换:Gateway 可以将外部请求的协议转换为微服务所需要的协议,例如将 HTTP 请求转换为 gRPC 请求,从而使不同协议的微服务能够无缝协同工作。
- 日志与监控:Gateway 可以在请求转发过程中记录日志,并提供监控和指标数据,帮助开发人员和运维人员了解系统的运行情况、故障排查等。
- 灰度发布:Gateway 可以实现服务的灰度发布,将部分请求流量引导到新版本的微服务上,以验证新功能或修复的问题,同时保持旧版本的稳定运行。
集成gateway
导入Maven依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
gateway的使用
路由转发
spring:
cloud:
gateway:
routes:
# 路由id
- id: test_gateway
# 路由转发的url,这样的配置可以通过nacos进行访问
uri: lb://service-A
# 路由匹配条件
predicates:
# 匹配hello的所有请求
- Path=/hello/**
# 匹配主机名以example.com结尾的主机名
- Host=**.example.com
# 匹配请求的方法为GET的请求
- Method=GET
# 匹配header中X-Request-Id参数,且数据为数字,\d+表示匹配多个数字
- Header=X-Request-Id, \d+
# 匹配id为12345的请求
- Query=id,12345
# 匹配访问的ip地址结尾从0-255
- RemoteAddr=192.168.1.0/24
filters:
# 向请求添加请求头, key为X-Request-Foo,value为Bar
- AddRequestHeader=X-Request-Foo, Bar
# 向响应体加请求头,key为X-Response-Foo,value为Bar
- AddResponseHeader=X-Response-Foo, Bar
# 重写路径将segment.*,url写成segment
- RewritePath=/foo/(?<segment>.*), /${segment}
# 使用熔断处理
- name: Hystrix
args:
name: myCommand
# 移除一个前缀
- StripPrefix=1
# 重试机制
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY, GATEWAY_TIMEOUT
methods: GET, POST
lb:// 是 Spring Cloud Gateway 用于负载均衡的 URI 标识符,它会使用 Spring Cloud LoadBalancer 来寻找服务实例。
自定义 GlobalFilter
public class TestFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 编写逻辑,进入下一个过滤器
if (true){
return chain.filter(exchange);
}
// 不满足要求进行处理
throw new RuntimeException("错误");
}
@Override
public int getOrder() {
return 0;
}
}
自定义GatewayFilter
public class TestGatewayFilter extends AbstractGatewayFilterFactory<TestGatewayFilter.Config> {
@Override
public GatewayFilter apply(Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 执行逻辑
if (true){
return chain.filter(exchange);
}
throw new RuntimeException("错误");
}
};
}
public static class Config {
private String businessAttributes;
public String getBusinessAttributes() {
return businessAttributes;
}
public void setBusinessAttributes(String businessAttributes) {
this.businessAttributes = businessAttributes;
}
}
}
GlobalFilter与GatewayFilter的区别
GlobalFilter是全局的,意为对全部的请求进行修改
GatewayFilter是局部的,只有经过该过滤器的请求才会进行修改
安全与认证
可以在全局过滤器中进行token的校验,校验token是否可被解析。
流量控制
spring:
cloud:
gateway:
default-filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
配置bean
@Configuration
public class RateLimiterConfig {
@Bean
public RequestRateLimiterGatewayFilterFactory rateLimiter() {
return new RequestRateLimiterGatewayFilterFactory();
}
}
协议切换
spring:
cloud:
gateway:
routes:
# 路由id
- id: test_gateway
uri: lb://service-A
# 路由匹配条件
filters:
# 向请求添加请求头, key为X-Request-Foo,value为Bar
- AddRequestHeader=X-Request-Foo, Bar
编写controller
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/hello")
public String getHello(@RequestHeader("X-Request-Foo")String header){
return "Received header: " + header;
}
}
当uri为service-A时会在请求的header中添加Bar,这样就会将请求请求到下级服务中
日志与监控
可以通过yaml中配置Prometheus 监控服务器进行监控。
灰度发布
灰度发布就是在当前版本中发布最新版本,一种逐步将新版本的服务引入生产环境的方法。
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: service-v1
uri: http://localhost:8081
predicates:
- Path=/api/**
filters:
- name: GrayReleaseFilter
args:
weight: 50 # 表示 50% 的流量
- id: service-v2
uri: http://localhost:8082
predicates:
- Path=/api/**
filters:
- name: GrayReleaseFilter
args:
weight: 50 # 表示 50% 的流量
编写gatewayFilter
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import java.util.Random;
@Component
public class GrayReleaseFilter extends AbstractGatewayFilterFactory<GrayReleaseFilter.Config> {
public static class Config {
private int weight;
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
public GrayReleaseFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
// 使用随机数来决定请求分配到哪个版本
Random random = new Random();
if (random.nextInt(100) < config.getWeight()) {
// 将请求分配到新的版本
return chain.filter(exchange.mutate().request(request.mutate().header("Gray-Version", "v2").build()).build());
} else {
// 将请求分配到旧的版本
return chain.filter(exchange.mutate().request(request.mutate().header("Gray-Version", "v1").build()).build());
}
};
}
}
原理分析
gateway通过配置的形式映射到Java类上,而映射的实例是GatewayProperties
globalFilter
该过滤器是gateway中的全局过滤器,拦截所有http请求,根据predicate过滤得到满足条件的uri
GatewayFilter
由开发人员操作,可以对predicate过滤后满足条件的uri,进行属性的添加,比如:在header加上参数之类的。
综上所述,gateway的执行流程如下:
1.将yaml配置转化为JavaBean -> 2.加载routeDefinitionLocator -> 3.执行全局过滤器GlobalFilter -> 4.加载RouteDefinition、predicates、filters参数