Spring Cloud Gateway

zuul终究还是被时代淘汰了,spring基本上也逐渐放弃了Netflix平台,自己搞起了gateway。这不得不聊起一个人 Spencer Gibb,他是zuul的核心开发,带领一群有志青年,放弃zuul,转战spring cloud gateway。

应用搭建

其maven依赖如下:

xml 复制代码
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

之后,只需要写个简单的spring boot程序就可以了,与zuul不同的是,gateway没有@Enable开头的开关:

java 复制代码
@SpringBootApplication
public class GatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

这就是gateway与zuul设计哲学的不同。

网关配置

光完成上述代码肯定不够,因为没有配置转发。以下是配置文件的一个例子:

yml 复制代码
server:
  port: 80 # 网关端口

spring:
  cloud:
    gateway:
      routes:
        - id: user_route
          # 直接写死目标服务的 IP 和端口
          uri: http://127.0.0.1:8001
          predicates:
            - Path=/user/**

之后就可以正常转发了。

谓词配置

配置中的predicates是gateway的谓词,这部分可谓非常复杂了。上述例子里用的是路径谓词。此外我还整理了其他比较好用的谓词.

谓词名称 用途 典型场景
Path 匹配请求路径 /api/ 转发给某个服务
Query 匹配请求参数 根据 URL 中的参数(如版本号)分流
Header 匹配请求头 根据 User-Agent 或自定义 Header 鉴权
Method 匹配请求方法 只允许 GET 或 POST 请求通过
Cookie 匹配 Cookie 针对特定用户群体的灰度发布
Host 匹配域名 基于域名的路由(如 *.abc.com
RemoteAddr 匹配客户端 IP 黑白名单、IP 限流
After/Before 匹配时间 活动期间开启特定页面,或维护窗口

过滤器

除了谓词以外,gateway还提供了过滤器配置,以达到更精致的网关控制。以下是常见的过滤器:

分类 过滤器名称 (Filter Name) 核心作用
请求处理 AddRequestHeader 给请求头添加自定义信息
AddRequestParameter 给请求添加参数
RewritePath 重写请求路径(最常用)
StripPrefix 截断请求路径前缀
RequestRateLimiter 请求限流(令牌桶算法)
响应处理 AddResponseHeader 给响应头添加信息
DedupeResponseHeader 去除响应头中重复的值
SetStatus 修改返回的状态码
路由增强 Hystrix 熔断保护(旧版)
RequestSize 限制请求包大小
Retry 失败自动重试

转发实现

gateway是怎么转发的?gateway是基于WebFlux技术的。gateway写了一个RoutePredicateHandlerMapping,该类实现了HandlerMapping接口,所以充当了传统servlet里控制器的角色。核心方法在lookupRoute里。在追踪gateway源码时我们可以记录一下堆栈的变化。

  1. 线程Threadreactor-http-nio-2,5,main

at org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping.lookupRoute(RoutePredicateHandlerMapping.java:128)

at org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping.getHandlerInternal(RoutePredicateHandlerMapping.java:87)

at org.springframework.web.reactive.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:181)

  1. 线程Threadreactor-http-nio-2,5,main

at org.springframework.cloud.gateway.handler.FilteringWebHandler.handle(FilteringWebHandler.java:77)

at org.springframework.web.reactive.result.SimpleHandlerAdapter.handle(SimpleHandlerAdapter.java:45)

at org.springframework.web.reactive.DispatcherHandler.invokeHandler(DispatcherHandler.java:161)

  1. 线程Threadreactor-http-nio-2,5,main

at org.springframework.cloud.gateway.filter.NettyRoutingFilter.filter(NettyRoutingFilter.java:104)

at org.springframework.cloud.gateway.handler.FilteringWebHandler$GatewayFilterAdapter.filter(FilteringWebHandler.java:138)

at org.springframework.cloud.gateway.filter.OrderedGatewayFilter.filter(OrderedGatewayFilter.java:44)

NettyRoutingFilter这个类里终于找到了转发的代码了,我只贴一行代码,不过这行代码可够长的了:

java 复制代码
Flux<HttpClientResponse> responseFlux = this.httpClient.headers(headers -> {
			headers.add(httpHeaders);
			if (preserveHost) {
				String host = request.getHeaders().getFirst(HttpHeaders.HOST);
				headers.add(HttpHeaders.HOST, host);
			}
			else {
				// let Netty set it based on hostname
				headers.remove(HttpHeaders.HOST);
			}
		}).request(method).uri(url).send((req, nettyOutbound) -> {
			if (log.isTraceEnabled()) {
				nettyOutbound.withConnection(connection -> log.trace(
						"outbound route: " + connection.channel().id().asShortText()
								+ ", inbound: " + exchange.getLogPrefix()));
			}
			return nettyOutbound.send(request.getBody()
					.map(dataBuffer -> ((NettyDataBuffer) dataBuffer).getNativeBuffer()));
		}).responseConnection((res, connection) -> {

			// 省略很多很多代码。。。。。。。

			return Mono.just(res);
		});
相关推荐
君顾11 小时前
代驾跑腿业务系统实战开发指南
java·开发语言·代驾跑腿
NGINX开源社区2 小时前
NGINX Ingress Controller 5.5:安全性与性能提升,迁移更轻松
java·服务器·nginx
云烟成雨TD2 小时前
Micrometer 系列【25】Spring Boot Actuator | Spring MVC、Spring WebFlux 指标
java·spring boot·micrometer
liudashuang20172 小时前
Kafka Producer 隐藏深坑:Sender 线程自阻塞(自死锁)导致 BufferExhaustedException 完整复盘
java·分布式·kafka·linq
风筱2 小时前
Idea的CC GUI插件安装Claude Code SDK失败
java·ide·ai编程
m0_527034332 小时前
异步任务审核系统设计:消息队列、超时重试与失败补偿
java·大数据·开发语言
xbgRS2 小时前
springBoot项目配置加载优先级
java·spring boot
zzzll11112 小时前
Loop Engineering:循环工程的原理、实践与应用
java·数据库·python
假客套2 小时前
记一次若依 Excel 导出踩坑:Permission denied、401 报错完整排查记录
java·若依·linux服务器
岁岁养乐多3 小时前
深入解析 Spring @Cacheable 注解:从声明式缓存 到多维替代方案
java