Gateway网关
1.背景说明:
SpringCloud Gateway 是SpringCloud的一个全新项目,基于Spring5.0+Spring Boot 2.0和Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。
SpringCloud Gateway 作为SpringCloud生态系统中的网关,目标是替代Zuul,在Spring Cloud 2.0以上版本中,没有对新版本Zuul2.0以上最高性能版进行集成,仍然耗时使用Zuul1.x非Reactor模式的老版本,而为了提高网关的性能,SpringCloud Gateway 是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty
一句话概括Gateway:SpringCloud Gateway 使用的是WebFlux中的Reactor-Netty响应式编程组件,底层使用了Netty通讯框架。
SpringCloud Gateway 的目标就是提供统一的路由方式且基于Filter链的方式提供了网关基本功能,例如:安全,监控/指标,和限流。
2. Zuul与Gateway区别
1、Zuul 1.x,是基于阻塞I/O 的API Gateway
2、Zuul 1.x是基于Servlet2.5使用阻塞架构,它不支持任何长连接(如WebSocket)Zuul的设计模式和Nginx较像,每次I/O操作都是从工作线程中选择一个执行,请求线程被阻塞到工作线程完成,但是差别是从Nginx用C++实现,Zuul用java实现,而JVM本身会有第一次加载较慢的情况,是的Zuul的性能相对较差
3、Zuul2.x理念更先进,像基于Netty非阻塞和至此长连接,但SpringCloud目前没有整合,Zuul2.x的性能较1.x有较大提升,在性能方面,根据官方提供的基准测试,SpringCloud Gateway 的RPS(每秒请求数)是Zuul的1.6倍
4、SpringCloud Gateway 建立在SpringFramework5、Project Reactor和Spring Boot2.x之上,使用费阻塞API
5.SpringCloud Gateway还支持WebSocket,并且与Spring紧密集成,拥有更好的开发体验。
3. Gateway的概念
1. Route(路由):路由是构建网关的基本模块,它由ID,目标URL,一系列的断言和过滤器注册,如果断言为true,则匹配该路由
2. Predicate(断言):断言参考的是JAVA8的函数式编程,开发人员可以匹配HTTP请求中的所有内容,例如(请求头或者请求体),如果请求与断言相匹配则进行路由
3. Filter(过滤):指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前,或者之后,对请求进行修改。
4. 工作流程核心逻辑:路由转发+执行过滤器链
5. 总结:web请求,通过一些匹配条件,定位到真正的服务节点,并在这个转发过程的前后,进行一些精细化控制。predicate就是我们的匹配条件,而filter,就可以理解为一个无所不能的拦截器,有了这两个元素,再加上目标uri,就可以实现一个具体的路由了
4.实操GateWay
4.1 配置文件方式
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
uri: http://localhost:8001 #匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** # 断言,路径相匹配的进行路由
原8001服务端请求:
GateWay9527端口请求
4.2 GateWay代码方式配置
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder){
RouteLocatorBuilder.Builder routes = builder.routes();
//外网转发至百度新闻国内
routes.route("path_route_guonei",
r-> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
//外网转发至百度新闻国内
routes.route("path_route_guoji",
r -> r.path("/guoji").uri("http://news.baidu.com/guoji")).build();
return routes.build();
}
}
效果:
可以看到,地址为http://localhost:9527/guonei,确跳到了百度新闻国内板块
5.动态路由
以上的配置文件配置,可以看出地址,端口写死了,这种方式在多服务的集群部署方式中并不可取,所以需要配置动态配置,并实现负载均衡
修改yml开启动态路由: 增加discovery.locator.enabled: true
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** # 断言,路径相匹配的进行路由
同时启动8001,8002
eureka注册中心:
请求9527:
6.GateWay常用的Predicate
- After Rote Predicate
- Before Rote Predicate
- Between Rote Predicate
- Cookie Rote Predicate
- Header Rote Predicate
- Host Rote Predicate
- Method Rote Predicate
- Path Rote Predicate
- Query Rote Predicate
示例:
- After Rote Predicate
如下配置,在predicates:下加入After 设置某个时间,当时间未到时,访问接口返回404,时间到了之后,可正常访问
- id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/payment/payment-getPaymentLb/** # 断言,路径相匹配的进行路由
- After=2021-07-21T15:51:37.485+08:00[Asia/Shanghai]
After效果:
用途:此设置可结合服务降级等方案,设计例如秒杀活动接口路径,未到时间不可访问,秒杀开始后方可访问秒杀详情页面。
predicate总结:Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理
7.GateWay的Filter过滤器
简单案例,实现用户访问日志:
7.1 Filter过滤器类实现GlobalFilter, Ordered
7.2 代码
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("************** come in MyLogGateWayFilter : " + DateUtil.date());
String username = exchange.getRequest().getQueryParams().getFirst("username");
if (StringUtils.isEmpty(username)) {
log.error("***********用户非法,禁止访问!o(╥﹏╥)o");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
log.info("当前用户:" + username);
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
7.3 实现效果:
不带username访问接口
带username访问时:访问成功,打印日志
以上:SpringCloud GateWay整理完毕。
本文根据尚硅谷阳哥springCloud视频整理,视频地址:https://www.bilibili.com/video/BV18E411x7eT
个人学习代码仓库地址:https://gitee.com/javaeelhb/cloud2021/tree/haibo.li/