Gateway工作机制
文中内容包含:微服务网关限流10万QPS、跨域、过滤器、令牌桶算法。
在德邦快递的微服务实践中,API网关提供了统一的认证、鉴权、API 监控、熔断、限流、降级等功能。当然,熔断、限流、降级在注册中心也会进行一次。
https://www.cnblogs.com/doondo/p/15070715.html good
https://www.cnblogs.com/mrxiaobai-wen/p/14268696.html
RateLimiter和Java中的信号量(java.util.concurrent.Semaphore)类似,Semaphore通常用于限制并发量.
Gateway网关路由有两种配置方式:
1、在配置文件yml中配置
2、代码中注入RouteLocator的Bean
这两种方式是等价的,建议使用yml配置方式
网关跨域配置,网关过滤器编写,网关的令牌桶算法限流【每秒10万QPS】
当client端使用http://localhost:8098/consumer/user/info路径进行请求时,如果根据上述进行配置Gateway会将请求转换为http://localhost:8098/service-consumer/user/info。以此作为前端请求的最终目的地。
- id: box-items-service
uri: lb://box-items-service
predicates:
- Path=/open/items/**
filters:
# 表示截取路径的个数
- StripPrefix=1
nginx Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务
zuul ,Zuul 是 Netflix 出品的一个基于 JVM 路由和服务端的负载均衡器。
spring-cloud-gateway, 是spring 出品的 基于spring 的网关项目,集成断路器,路径重写,性能比Zuul好。
- 安全 ,只有网关系统对外进行暴露,微服务可以隐藏在内网,通过防火墙保护。
- 易于监控。可以在网关收集监控数据并将其推送到外部系统进行分析。
- 易于认证。可以在网关上进行认证,然后再将请求转发到后端的微服务,而无须在每个微服务中进行认证。
- 减少了客户端与各个微服务之间的交互次数
- 易于统一授权。
微服务网关就是一个系统,通过暴露该微服务网关系统,方便我们进行相关的鉴权,安全控制,日志统一处理,易于监控的相关功能。
2.2 微服务网关跨域
在启动类GatewayApplication中,加入跨域配置代码如下
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedMethod("*");//支持所有方法
config.addAllowedOrigin("*");//跨域处理 允许所有的域
config.addAllowedHeader("*");//支持所有请求头
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", config);//匹配所有请求
return new CorsWebFilter(source);
}
三、微服务网关过滤器
我们可以通过网关过滤器,实现一些逻辑的处理,比如ip黑白名单拦截、特定地址的拦截等。下面的代码中做了两个过滤器,并且设定的先后顺序。
在网关微服务中创建IpFilter,无需配置其他,注册到Spring容器即可生效
@Component
public class IpFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
InetSocketAddress remoteAddress = request.getRemoteAddress();
//TODO 设置ip白名单
System.out.println("ip:"+remoteAddress.getHostName());
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 1;
}
}
在网关微服务中创建UrlFilter,无需配置其他,注册到Spring容器即可生效
@Component
public class UrlFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String url = request.getURI().getPath();
//TODO 拦截特定URL地址
System.out.println("url:"+url);
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 2;
}
}
四、网关限流每秒10万请求
我们之前说过,网关可以做很多的事情,比如,限流,当我们的系统 被频繁的请求的时候,就有可能 将系统压垮,所以 为了解决这个问题,需要在每一个微服务中做限流操作,但是如果有了网关,那么就可以在网关系统做限流,因为所有的请求都需要先通过网关系统才能路由到微服务中。
4.2 令牌桶算法 介绍
令牌桶算法是比较常见的限流算法之一,大概描述如下:
1)所有的请求在处理之前都需要拿到一个可用的令牌才会被处理; 2)根据限流大小,设置按照一定的速率往桶里添加令牌; 3)桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃或者拒绝; 4)请求达到后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除; 5)令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保证足够的限流
这个算法的实现,有很多技术,Guava(读音: 瓜哇)是其中之一,redis客户端也有其实现。
4.3 网关限流代码实现
需求:每个ip地址1秒内只能发送10万请求,多出来的请求返回429错误。
(1)spring cloud gateway 默认使用redis的RateLimter限流算法来实现。所以我们要使用首先需要引入redis的依赖
有pre和post两种方式的filter,分别处理前置逻辑和后置逻辑。客户端的请求先经过pre类型的filter,然后将请求转发到具体的业务服务,收到业务服务的响应之后,再经过post类型的filter处理,最后返回响应到客户端。
过滤器执行流程如下,order越大,优先级越低
@Slf4j
public class AFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("AFilter前置逻辑");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("AFilter后置逻辑");
}));
}
}
/**
* http://localhost:8100/filter/provider
* @param builder
* @return
*/
@Bean
public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) {
// @formatter:off
// 可以对比application.yml中关于路由转发的配置
return builder.routes()
.route(r -> r.path("/filter/**")
.filters(f -> f.stripPrefix(1)
.filter(new ElapsedFilter()))
.uri("lb://idc-cloud-provider")
.order(0)
.id("filter")
)
.build();
// @formatter:on
}
d:我们自定义的路由 ID,保持唯一
uri:目标服务地址
predicates:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该属性包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)
https://zhuanlan.zhihu.com/p/299608850