
微服务学习之网关(Gateway / Sentinel)路由及熔断限流
微服务系列
1、Nacus 服务搭建及使用
2、Nacos 配置中心
3、Nacos 服务注册与发现之OpenFeign服务间调用
4、Spring Security & Oauth2 认证授权
5、网关(Gateway / Sentinel)路由及熔断限流
6、网关(Gateway自定义断言和过滤器)
文章目录
前言
之前面试总是碰到面试官对网关Gateway的问题,之前只是用过Netflix的Zuul的路由转发和调用了认证授权服务进行对用户访问的控制,其实Gateway的功能更强,这不周末在吃喝玩乐的闲暇时间,还是需要学习一下才不枉周末时光。
一、Gateway基本介绍?
Gateway见词知意,就是大门的意思,大门呢就是一整个院子的入口,是比较重要的,关系着院内的安全和用户的同一入口引导。
所以Spring Cloud 中的Gateway作为网关的身份担任着重要的角色,常用的功能包括路由转发、权限校验、限流、安全等。
Gateway是Spring Cloud官方推出的第二代网关框架,是有 WebFlux+Netty+Reactor实现的响应式API网关,很好的代替了zuul,有更优秀的性能,更强大的功能。
Gateway对外暴露了统一的访问入口,使得客户端调用后端服务更加方便。
二、核心概念
- 路由(Route):官方原话是这样说的(The basic building block of the gateway. It is defined by an ID, a destination URI, a collection of predicates, and a collection of filters. A route is matched if the aggregate predicate is true.),就是一个基本构建版块,一个ID, 一个URL,一组断言和一组过滤器组成,如果断言为True,这说明访问的路径合法。
- 断言(Predicate):官方原话(This is a Java 8 Function Predicate. The input type is a Spring Framework ServerWebExchange. This lets you match on anything from the HTTP request, such as headers or parameters.),断言是 java 8 的断言函数,输入就是一个Spring框架的Web交换机,断言运行开发者自定义匹配HTTP请求里面的任何信息。
- 过滤器(Filter):官方原话(These are instances of GatewayFilter that have been constructed with a specific factory. Here, you can modify requests and responses before or after sending the downstream request.),就是说,GatewayFilter是为特别的因素构建的,可以对请求之前和响应之后进行处理。GlobalFilter就是全局的过滤器。
三、How it works
四、Gateway服务搭建及路由配置
1、pom依赖
这里没有版本控制,因为上面用了统一的Spring Cloud版本控制器。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
2、application.yml 配置
2.1、路由断言工厂
Gateway 内置了很多路由断言工厂类,在服务启动的时候就会加载,下面是日志。
所以我们服务中直接可以用到这些路由器来实现我们的业务。
2.2、路由断言Path配置
下面的配置,当访问 http://localhost:8088/home-server/api/** 路径是,会转发到 home-server这个服务调用。
server:
port: 8088 #服务端
spring:
application:
name: gateway-server
#配置gateway
cloud:
gateway:
#路由规则
routes:
- id: home-server #路由的唯一标识
uri: http://localhost:8001
predicates:
- Path=/home-server/** #需要断言的路径
filters:
- StripPrefix=1 #替换调 home-server实现跳转
访问测试 红框里的 home-server就是要转发的服务。
2.3、路由断言工厂After、Before、Between 配置
别的配置不变,只需要在 predicates 下面加上 After 配置就可以限制在配置的时间节点后访问了,这个时间点之前访问不了。
比如下面的配置是 在 2000-08-28 之后才可以访问,今天是 2022-08-27 访问就是 404。
predicates:
...
- Path=/home-server/** #需要断言的路径
- After=2022-08-28T22:22:07.783+08:00[Asia/Shanghai]
Before 、Between 和 After 一样,需要注意的是配置的时间格式必须是 ZonedDateTime类型的指定日期时间,
这样获取时间
ZonedDateTime zonedDateTime = ZonedDateTime.now();
ZonedDateTime zonedDateTime2 = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
2.4、路由断言工厂Cookie 配置
Cookie配置则需要在 predicates下面配置上 Cookie 参数即可,在访问的时候就会校验请求头里面的参数。
...
predicates:
- Path=/home-server/** #需要断言的路径
- Cookie=username,phen
下面测试结果中,如果 username的是是错误的,则访问失败,把值改了再试一下,见下面的两张结合结果截图。
2.5、路由断言Header配置
predicates:
- Path=/home-server/** #需要断言的路径
- Header=Request-Id,\d+ #支持正则
2.6、路由断言 Host 配置
注意:我是在本地配置了 hosts 文件(127.0.0.1 www.text.com)并且网关服务的端口是 80。
...
routes:
- id: home-server # 路由的唯一标识
uri: http://localhost:8001
predicates:
- Host=**.text.com
2.7、路由断言 Method 配置
只有GET,POST请求才会路由。
...
routes:
- id: home-server # 路由的唯一标识
uri: http://localhost:8001
predicates:
- Method=GET,POST
2.8、路由断言 Query 配置
只有请求带了 token 参数才路由。
routes:
- id: home-server # 路由的唯一标识
uri: http://localhost:8001
predicates:
- Query=token
2.9、路由断言 RemoteAddr 配置
ip 后面的子网掩码没测试成功,带详查。
routes:
- id: home-server # 路由的唯一标识
uri: http://localhost:8001
predicates:
- RemoteAddr=192.168.1.12
2.10、路由断言 Weight 配置
80%的请求会路由到 8001, 20%的请求会路由到 8002。
routes:
- id: home-server_high # 路由的唯一标识
uri: http://localhost:8001
predicates:
- Weight=group1,8
- id: home-server_low
uri: http://localhost:8002
predicates:
- Weight=group1,2
测试结果:
打印出来日志验证,如下图:
可见 8001 访问日志为 8个,8002 为 2个。
3、启动类(忽略)
写这个完全是为了凑够篇幅,O(∩_∩)O哈哈~
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
五、Gateway 整合 Sentinel(熔断、限流)
5.1 引入依赖
在 Spring Cloud Alibaba 2.1.6之前的版本,引入的是 sentinel-spring-cloud-gateway-adapter 包,并且需要自己实现好多配置类,2.1.6 之后的版本内部已经帮我们实现好了,所以使用起来比较简单了。
版本由父pom控制。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--2.1.6之前的版本是 adapter 的包,整合比较麻烦,需要写配置类-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
5.2、配置 application.yml
需要 配置的是 gateway 和 sentinel
server:
port: 8089 #服务端
spring:
application:
name: gateway-server
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway: #配置gateway
discovery:
locator:
enabled: true #默认为false,true:开启通过微服务名访问
enabled: true # 是否开启网关
sentinel: # 配置sentinel
transport:
dashboard: localhost:8080
5.3、sentinel 启动
sentinel 基本使用时比较简单的,只需要从官网下载并启动就可以使用了,默认端口(8080),用户名(sentinel)和密码(sentinel)启动成功如下:
5.4、sentinel 配置限流规则
5.4.1、规则配置
以下配置说明:
API 名称:这个相当于一个服务的一个API的唯一ID;
阈值类型:1个 QPS 是完整的一次请求,发出请求并且拿到完成的请求结果;
QPS 阈值:每秒最大的QPS数;
间隔:请求间隔最大时间;
Burst size:宽容次数,比如我配置的是每秒访问3次以上进行流控,如果这个参数设置为 1 ,则每秒访问 4 次以上进行流控。
5.4.2、测试结果
我用postman每秒请求3次以上,则返回 429 (429 是 Too Many Request 错误码)。
5.5、sentinel 配置熔断规则
5.5.1、配置路由
下面配置中:
配置的路由 id 是 home-server,lb 是 负载均衡配置。
spring:
application:
name: gateway-server
cloud:
nacos:
config:
namespace: 16201af3-217e-468c-bc9c-0f2a9ee04912
server-addr: localhost:8848
file-extension: yaml
discovery:
namespace: 16201af3-217e-468c-bc9c-0f2a9ee04912
server-addr: localhost:8848
sentinel:
transport:
port: 8719
dashboard: localhost:8080
gateway: #配置gateway
routes:
- id: home-server
uri: lb://home-server
predicates:
- Path=/home/**
5.5.2、规则配置
以 异常数 降级来举例
熔断策略:以什么样的策略熔断;
慢调用比例:请求超过最大RT值,比如 1ms;
熔断时长:接口发生异常后熔断时长;
最小请求次数:每秒请求最少的失败次数;
统计时长:在一定的时间段内最少请求 2 次,每个请求超过1ms, 请求数量大于 50%;
5.5.3、测试结果
用 postman 快速发送请求,则会熔断,返回 DegradeException 异常,降级异常。
5.5.4、自定义流控降级异常信息
5.5.4.1、 通过配置类配置
在 SentinelConfig 类中加入 init() 初始化方法(要用 @PostConstruct 注解进行初始化),定义异常处理提示信息即可。
@PostConstruct
public void init(){
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map<String, String> result = new HashMap<>();
result.put("code", HttpStatus.TOO_MANY_REQUESTS.toString());
result.put("msg", "服务压力过大,请稍后重试!");
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(result));
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
5.5.4.2、通过application.yml 配置
主要配置 spring.cloud.sentinel.scg.fallback 即可。
spring:
cloud:
sentinel:
transport:
port: 8719
dashboard: localhost:8080
scg:
fallback:
mode: response
response-body: '{"code":"429 TOO_MANY_REQUEST", "msg":"服务压力过大,请稍后重试!"}'
5.5.4.3、测试结果
配置服务流控或者降级,阈值设置为1(总之小一点),postman 快速发送请求返回自定义服务流控降级信息。
总结
如今的微服务可以说是互联网公司的开发必备了,因为互联网公司的业务、用户量、以及针对以后的扩展和功能添加等相对都比较高,所以微服务就是最好的不二之选。
Gateway呢就是各个微服务的入口了,也是公司后台服务的大门,也是公司后台服务安全的第一道防护(有可能上一次也可以做安全控制),学习并记录这一特技,技多不压身,挺好。
小生不才,感谢赏光!!!
更多推荐
所有评论(0)