我在处理 websocket 连接的聊天服务前面运行云网关服务。 我们是否有一些方便的方法来记录网关端套接字客户端和聊天服务之间发生的交互?
我注意到云网关利用
org.springframework.cloud.gateway.filter.WebsocketRoutingFilter
来代理 websockets 但不确定如何加入它的派对以及它是否适合去
目前我还没有找到将自己的拦截器附加到框架提供的工具的方法。所以我决定复制粘贴的 WebsocketRoutingFilter 实现,使用 @Primary 注释并以这种方式注入自己的逻辑。
Original
WebsocketRoutingFilter
在内部创建 ProxyWebSocketHandler
的实例来处理套接字会话,并且有一个方法 handle
可以被扩充。
还要注意代表每条消息的
DataBuffer
。它控制已经读取的数据量。所以我决定以这种方式阅读消息:
private String readBufferedMessage(DataBuffer dataBuffer) {
DataBuffer slice = dataBuffer.slice(0, dataBuffer.capacity());
byte[] bytes = new byte[slice.readableByteCount()];
slice.read(bytes);
return new String(bytes, StandardCharsets.UTF_8);
}
Spring Cloud Gateway 是一个功能强大的 API 网关,它提供了一种简单而有效的方法来路由和过滤传入的 HTTP 请求。虽然它不是专门为 WebSocket 使用而设计的,但它可以用于通过配置自定义过滤器来路由 WebSocket 流量。
要在 Spring Cloud Gateway 中使用过滤器获取 WebSocket 内容,您可以创建一个自定义过滤器,使用 DataBuffer 和 DataBufferUtils 类提取 WebSocket 有效负载。这是一个例子:
@Component
公共类 WebSocketFilter 实现 GatewayFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return DataBufferUtils.join(exchange.getRequest().getBody())
.flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
DataBufferUtils.release(dataBuffer);
String payload = new String(bytes, StandardCharsets.UTF_8);
// Do something with the WebSocket payload here
return chain.filter(exchange);
});
}
}
在这个例子中,WebSocketFilter类实现了GatewayFilter接口并覆盖了它的filter方法。该方法首先使用 DataBufferUtils.join 将整个 WebSocket 负载读入单个 DataBuffer。然后,它从 DataBuffer 中提取字节,使用 UTF-8 字符集将它们转换为字符串,最后在负载上应用一些自定义逻辑。最后,过滤器通过调用 chain.filter(exchange) 沿着过滤器链传递交换。
要在 Spring Cloud Gateway 配置中使用 WebSocketFilter,您需要将其添加到过滤器链中。这是一个示例 application.yml 文件,演示了如何执行此操作:
spring:
cloud:
gateway:
routes:
- id: websocket_route
uri: ws://localhost:8080/echo
predicates:
- Path=/websocket
filters:
- WebSocketFilter
在这个例子中,我们定义了一个 ID 为 websocket_route 的路由,它将传入的 WebSocket 请求转发到 ws://localhost:8080/echo 端点。我们使用 Path 谓词来匹配 /websocket 路径上的传入请求,并将自定义 WebSocketFilter 添加到过滤器链中以提取 WebSocket 有效负载。
请注意,此示例仅从 WebSocket 消息中提取有效负载,但您可以修改 WebSocketFilter 类以从消息中提取您需要的任何信息。