1、Nacus 服务搭建及使用
2、Nacos 配置中心
3、Nacos 服务注册与发现之OpenFeign服务间调用
4、Spring Security & Oauth2 认证授权
5、网关(Gateway)的搭建及使用
6、网关(Gateway自定义断言和过滤器)
之前面试总是碰到面试官对网关Gateway的问题,之前只是用过Netflix的Zuul的路由转发和调用了认证授权服务进行对用户访问的控制,其实Gateway的功能更强,这不周末在吃喝玩乐的闲暇时间,还是需要学习一下才不枉周末时光。
Gateway见词知意,就是大门的意思,大门呢就是一整个院子的入口,是比较重要的,关系着院内的安全和用户的同一入口引导。
所以Spring Cloud 中的Gateway作为网关的身份担任着重要的角色,常用的功能包括路由转发、权限校验、限流、安全等。
Gateway是Spring Cloud官方推出的第二代网关框架,是有 WebFlux+Netty+Reactor实现的响应式API网关,很好的代替了zuul,有更优秀的性能,更强大的功能。
Gateway对外暴露了统一的访问入口,使得客户端调用后端服务更加方便。
这里没有版本控制,因为上面用了统一的Spring Cloud版本控制器。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
Gateway 内置了很多路由断言工厂类,在服务启动的时候就会加载,下面是日志。
所以我们服务中直接可以用到这些路由器来实现我们的业务。
下面的配置,当访问 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就是要转发的服务。
别的配置不变,只需要在 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"));
Cookie配置则需要在 predicates下面配置上 Cookie 参数即可,在访问的时候就会校验请求头里面的参数。
...
predicates:
- Path=/home-server/** #需要断言的路径
- Cookie=username,phen
下面测试结果中,如果 username的是是错误的,则访问失败,把值改了再试一下,见下面的两张结合结果截图。
predicates:
- Path=/home-server/** #需要断言的路径
- Header=Request-Id,\d+ #支持正则
注意:我是在本地配置了 hosts 文件(127.0.0.1 www.text.com)并且网关服务的端口是 80。
...
routes:
- id: home-server # 路由的唯一标识
uri: http://localhost:8001
predicates:
- Host=**.text.com
只有GET,POST请求才会路由。
...
routes:
- id: home-server # 路由的唯一标识
uri: http://localhost:8001
predicates:
- Method=GET,POST
只有请求带了 token 参数才路由。
routes:
- id: home-server # 路由的唯一标识
uri: http://localhost:8001
predicates:
- Query=token
ip 后面的子网掩码没测试成功,带详查。
routes:
- id: home-server # 路由的唯一标识
uri: http://localhost:8001
predicates:
- RemoteAddr=192.168.1.12
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
写这个完全是为了凑够篇幅,O(∩_∩)O哈哈~
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
在 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>
需要 配置的是 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
sentinel 基本使用时比较简单的,只需要从官网下载并启动就可以使用了,默认端口(8080),用户名(sentinel)和密码(sentinel)启动成功如下:
以下配置说明:
API 名称:这个相当于一个服务的一个API的唯一ID;
阈值类型:1个 QPS 是完整的一次请求,发出请求并且拿到完成的请求结果;
QPS 阈值:每秒最大的QPS数;
间隔:请求间隔最大时间;
Burst size:宽容次数,比如我配置的是每秒访问3次以上进行流控,如果这个参数设置为 1 ,则每秒访问 4 次以上进行流控。
我用postman每秒请求3次以上,则返回 429 (429 是 Too Many Request 错误码)。
下面配置中:
配置的路由 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/**
以 异常数 降级来举例
熔断策略:以什么样的策略熔断;
慢调用比例:请求超过最大RT值,比如 1ms;
熔断时长:接口发生异常后熔断时长;
最小请求次数:每秒请求最少的失败次数;
统计时长:在一定的时间段内最少请求 2 次,每个请求超过1ms, 请求数量大于 50%;
用 postman 快速发送请求,则会熔断,返回 DegradeException 异常,降级异常。
在 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);
}
主要配置 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":"服务压力过大,请稍后重试!"}'
配置服务流控或者降级,阈值设置为1(总之小一点),postman 快速发送请求返回自定义服务流控降级信息。
如今的微服务可以说是互联网公司的开发必备了,因为互联网公司的业务、用户量、以及针对以后的扩展和功能添加等相对都比较高,所以微服务就是最好的不二之选。
Gateway呢就是各个微服务的入口了,也是公司后台服务的大门,也是公司后台服务安全的第一道防护(有可能上一次也可以做安全控制),学习并记录这一特技,技多不压身,挺好。
小生不才,感谢赏光!!!