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. 线程Thread[reactor-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. 线程Thread[reactor-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. 线程Thread[reactor-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);
		});
相关推荐
2501_944441752 小时前
Flutter&OpenHarmony商城App消息通知组件开发
java·javascript·flutter
we1less2 小时前
[audio] AudioTrack (四) getOutputForAttr 分析
android·java
计算机毕设指导62 小时前
基于微信小程序的博物馆文创系统【源码文末联系】
java·spring boot·微信小程序·小程序·tomcat·maven·intellij-idea
后端小张2 小时前
【JAVA 进阶】Spring Boot自动配置详解
java·开发语言·人工智能·spring boot·后端·spring·spring cloud
郝学胜-神的一滴2 小时前
Python面向对象编程:解耦、多态与魔法艺术
java·开发语言·c++·python·设计模式·软件工程
有趣灵魂2 小时前
Java SpringBoot批量获取Minio中多个文件进行压缩成zip下载
java·开发语言·spring boot
彭于晏Yan2 小时前
Spring集成kafka
spring·kafka
IT 行者2 小时前
Spring Security Session 序列化策略分析
java·spring boot·后端·spring
__万波__2 小时前
二十三种设计模式(十六)--迭代器模式
java·设计模式·迭代器模式