服务主要架构 springcloud
springboot
springcloud gateway 网关
nginx 反向代理

问题:

websocket客户端和服务端正常交互,但是发现会断开连接,不知道什么原因,客户端断开提示: WebsocketBase::onCloseWrapper code : 1009 reason:Max frame length of 65536 has bean exceeded. remote:true

分析:

大致意思还是 服务端处理不了这么大的数据帧,数据超过了65536 ,和上一个问题报的不一样,上次出现的原因是客户端建立和服务器建立连接,没有配置该session能接收多大的数据,现已配置如下图
在这里插入图片描述

到开发环境又出现这个问题,但是上个问题改过之后,本地调试正常的啊,本地调试时直接连接该服务,比较差异,开发环境经过nginx和网关服务,那么问题一定出现在了 网关或者是nginx上面了,就先排查网关,还真是网关的问题,通过google和查看源码发现

 */
public abstract class NettyWebSocketSessionSupport<T> extends AbstractWebSocketSession<T> {

	/**
	 * The default max size for inbound WebSocket frames.
	 */
	public static final int DEFAULT_FRAME_MAX_SIZE = 64 * 1024;

Netty的WebFlux中的WebSocket默认65536字节的帧,好了问题真相大白,重写此NettyWebSocketSessionSupport 类重新注入即可,但发现下面ReactorNettyRequestUpgradeStrategy 可以修改netty策略。

/**
 * A {@link RequestUpgradeStrategy} for use with Reactor Netty.
 *
 * @author Rossen Stoyanchev
 * @since 5.0
 */
public class ReactorNettyRequestUpgradeStrategy implements RequestUpgradeStrategy {

	private int maxFramePayloadLength = NettyWebSocketSessionSupport.DEFAULT_FRAME_MAX_SIZE;


	/**
	 * Configure the maximum allowable frame payload length. Setting this value
	 * to your application's requirement may reduce denial of service attacks
	 * using long data frames.
	 * <p>Corresponds to the argument with the same name in the constructor of
	 * {@link io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory
	 * WebSocketServerHandshakerFactory} in Netty.
	 * <p>By default set to 65536 (64K).
	 * @param maxFramePayloadLength the max length for frames.
	 * @since 5.1
	 */
	public void setMaxFramePayloadLength(Integer maxFramePayloadLength) {
		this.maxFramePayloadLength = maxFramePayloadLength;
	}

	/**
	 * Return the configured max length for frames.
	 * @since 5.1
	 */
	public int getMaxFramePayloadLength() {
		return this.maxFramePayloadLength;
	}


	@Override
	public Mono<Void> upgrade(ServerWebExchange exchange, WebSocketHandler handler,
			@Nullable String subProtocol, Supplier<HandshakeInfo> handshakeInfoFactory) {

		ServerHttpResponse response = exchange.getResponse();
		HttpServerResponse reactorResponse = ((AbstractServerHttpResponse) response).getNativeResponse();
		HandshakeInfo handshakeInfo = handshakeInfoFactory.get();
		NettyDataBufferFactory bufferFactory = (NettyDataBufferFactory) response.bufferFactory();

		return reactorResponse.sendWebsocket(subProtocol, this.maxFramePayloadLength,
				(in, out) -> {
					ReactorNettyWebSocketSession session =
							new ReactorNettyWebSocketSession(
									in, out, handshakeInfo, bufferFactory, this.maxFramePayloadLength);
					return handler.handle(session);
				});
	}

解决方法:

@Configuration
public class WebsocketFluxGatewayConfig {

    private static Integer DEFAULT_FRAME_MAX_SIZE = 100 * 1024;

    @Bean
    @Primary
    public WebSocketService customWebSocketService() {
        ReactorNettyRequestUpgradeStrategy requestUpgradeStrategy = new ReactorNettyRequestUpgradeStrategy();
        requestUpgradeStrategy.setMaxFramePayloadLength(DEFAULT_FRAME_MAX_SIZE);
        return new HandshakeWebSocketService(requestUpgradeStrategy);
    }
}

解决!!

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐