最近再弄soul网关,发现soul网关中的websocket插件路径和项目中的不匹配,重写弄了个websocket插件,顺便把gateway中的websocket看了一下,直接开撸
一、WebsocketRoutingFilter 解析
初始化WebsocketRoutingFilter
重要关注WebSocketClient webSocketClient
和WebSocketService webSocketService
WebSocketClient webSocketClient:连接后端【被代理】的 WebSocket 服务
WebSocketService webSocketService:处理客户端发起的ws连接请求
filter过滤方法
changeSchemeIfIsWebSocketUpgrade(exchange);
检查Upgrade是否为websocket
URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR):
获取请求连接路径
String scheme = requestUrl.getScheme();
if (isAlreadyRouted(exchange) || (!"ws".equals(scheme) && !"wss".equals(scheme))) {
return chain.filter(exchange);
}
判断scheme是否满足websocket连接条件
setAlreadyRouted(exchange);
设置已路由,exchange 中添加一个 gatewayAlreadyRouted 属性,从而将 exchange 标记为 routed(已路由)。一旦请求被标记为 routed ,其他路由过滤器将不会再次路由该请求,而是直接跳过。
return this.webSocketService.handleRequest(exchange,
new ProxyWebSocketHandler(requestUrl, this.webSocketClient,
filtered, protocols));
真正处理连接转发的地方
再来看看soul网关中添加的websocket自定义拦截器
二、SpringCloudWebsocketPlugin
初始化
this.loadBalancer = loadBalancer; 实现负载效果
this.webSocketClient = webSocketClient; 连接后端【被代理】的 WebSocket 服务
this.webSocketService = webSocketService; 处理客户端发起的ws连接请求
真正执行的方法体
首先final String serviceId = rule.getHandle();
获取到服务名
通过loadBalancer.choose(serviceId)
负载到要服务的具体实例
final URI uri = loadBalancer.reconstructURI(serviceInstance, URI.create(requestDTO.getPath()));
获取具体的uri
最后通过return this.webSocketService.handleRequest(exchange, new SpringCloudWebsocketPlugin.SoulWebSocketHandler( wsRequestUrl, this.webSocketClient, filterHeaders(headers), buildWsProtocols(headers)));
代理转发