在Netty高并发下可能会突然出现Channel.isWritable和Channel.isOpen的情况,主要是因为buffer缓冲区达到预设值。当buffer缓冲区大小超过高水位时,该Channel的isWritable状态为false变成不可发送; 当buffer缓冲区低于低水位线时,isWritable又会变回true,可以重新发送数据。
解决方法:

int lowWaterMark = (int) websocketProperties.getLowWaterMark().toBytes();
int highWaterMark = (int) websocketProperties.getHighWaterMark().toBytes();
//设置高低水位。当buffer缓冲区大小超过高水位时,该Channel的isWritable状态为false变成不可发送; 当buffer缓冲区低于低水位线时,isWritable又会变回true,可以重新发送数据
WriteBufferWaterMark writeBufferWaterMark = new WriteBufferWaterMark(lowWaterMark, highWaterMark);
//设置主从线程组
serverBootstrap.group(bossGroup, workerGroup)
        //配置写入高低水位
        .option(ChannelOption.WRITE_BUFFER_WATER_MARK, writeBufferWaterMark);

Netty完整代码:

//创建netty服务器
ServerBootstrap serverBootstrap = new ServerBootstrap();
int lowWaterMark = (int) websocketProperties.getLowWaterMark().toBytes();
int highWaterMark = (int) websocketProperties.getHighWaterMark().toBytes();
//设置高低水位。当buffer缓冲区大小超过高水位时,该Channel的isWritable状态为false变成不可发送; 当buffer缓冲区低于低水位线时,isWritable又会变回true,可以重新发送数据
WriteBufferWaterMark writeBufferWaterMark = new WriteBufferWaterMark(lowWaterMark, highWaterMark);
//设置主从线程组
serverBootstrap.group(bossGroup, workerGroup)
        .channel(NioServerSocketChannel.class)
        .childHandler(webSocketInitializer)
        //socket参数,当服务器请求处理程全满时,用于临时存放已完成三次握手请求的队列的最大长度。如果未设置或所设置的值小于1,Java将使用默认值50。
        .option(ChannelOption.SO_BACKLOG, 1024)
        //启用心跳保活机制,tcp,默认2小时发一次心跳
        .childOption(ChannelOption.SO_KEEPALIVE, true)
        //配置写入高低水位
        .option(ChannelOption.WRITE_BUFFER_WATER_MARK, writeBufferWaterMark)
        //接受数据buffer大小
        .option(ChannelOption.SO_RCVBUF, 256 * 1024)
        //发送数据buffer大小
        .option(ChannelOption.SO_SNDBUF, highWaterMark);

//绑定端口,异步任务回调
ChannelFuture future = serverBootstrap.bind(websocketProperties.getPort())
        .syncUninterruptibly();//同步等待
if (future != null && future.isSuccess()) {
    // 获取通道
    channel = future.channel();
    log.info("WebSocket server start success,port={}", websocketProperties.getPort());
} else {
    log.error("WebSocket server start fail");
}
最后修改:2022 年 09 月 04 日
如果觉得我的文章对你有用,请随意赞赏