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);
		});
相关推荐
devilnumber13 小时前
Java 递归算法 详解 + 核心要点 + 实战运用 + 避坑指南
java·开发语言·算法
asdfg125896315 小时前
JavaBean是什么?怎么理解?有什么用途?
java·开发语言
摇滚侠16 小时前
SpringMVC 入门到实战 文件上传 75-77
java·后端·spring·maven·intellij-idea
GIS数据转换器17 小时前
城市排水生命线安全运行监测平台深度解析
java·运维·人工智能·python·安全·数据挖掘·无人机
华如锦17 小时前
面了很多 Java转AI Agent方向,一些面试题总结
java·开发语言·人工智能·python·ai
睡不醒男孩03082317 小时前
CLup 6.x 版本中针对StarRocks 存算一体集群的完整操作手册
java·服务器·网络·clup
程序员黑豆18 小时前
Java中怎么实现字符串拼接呢【AI全栈开发】
java
java1234_小锋19 小时前
LangChain4j 开发Java Agent智能体- 多模态支持
java·开发语言·langchain4j
艳阳天_.19 小时前
星瀚弹框页面实现
java·前端·python