如何解决 Netty Channel.isWritable 返回 false

简介: 在 Netty 里,有4个方法用来查询 Channel 的状态:isOpen,isRegistered,isActive,isWritable,其中,isWritable 在并发量很高时会返回很多 false。 isWritable 是什么含义? isWritable:Returns true if and only if the I/O thread will perform the req

在 Netty 里,有4个方法用来查询 Channel 的状态:isOpen,isRegistered,isActive,isWritable,其中,isWritable 在并发量很高时会返回很多 false。

isWritable 是什么含义?

isWritable:Returns true if and only if the I/O thread will perform the requested write operation immediately. Any write requests made when this method returns false are queued until the I/O thread is ready to process the queued write requests.

为什么 isWritable 会返回 false?而且这个问题在 stackoverflow,netty 社区也被很多人问到。

i.e.

if (channel.isWritable()) {
    channel.writeAndFlush(data);
}

 

首先,说下 netty 处理 writeAndFlush 的原理:

1、业务线程调用 writeAndFlush 发送消息,会生成 WriteAndFlushTask,交由 IO 线程处理,write 操作将消息写入 ChannelOutboundBuffer(不会写到 socket),flush 操作将 ChannelOutboundBuffer 写 入socket 的发送缓冲区;(这里注意,writeAndFlush 它只是一个语法糖,意味着这不是原子操作,因此在此方法执行的中间,可能在多个线程之间进行了上下文切换。)

2、ChannelOutboundBuffer 它配置一个高水位线和低水位线,当 buffer 的大小超过高水位线的时候对应 channel 的 isWritable 就会变成 false,当 buffer 的大小低于低水位线的时候,isWritable 就会变成 true。

其中,高水位线和低水位线是字节数,默认高水位是64K,低水位是32K,通过以下方式进行设置:

.option(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, 64 * 1024)
.option(ChannelOption.WRITE_BUFFER_LOW_WATER_MARK, 32 * 1024)

 

如何解决这个问题?

ChannelOutboundBuffer 的容量过高或过低时都会触发 fireChannelWritabilityChanged 方法,因此可通过重写 channelWritabilityChanged 方法调整消息产生速度。

在常用的中间件里,我们看看它们是如何处理的:

1、Notify 在给订阅组投递消息时,先检查此订阅组的 Channel 是否超过最高位,如果是,则此次不投递,如果不是,继续投递。

2、Flink 核心发送方法中如果 Channel 不可写,则会跳过发送,当 Channel 再次可写后,Netty 会调用该 Handle 的 ChannelWritabilityChanged 方法,从而重新触发发送函数。

3、Duboo 发送请求时,判断是否已经关闭的 Channel,如果是,不再放入连接池,重新申请连接。

总之,在使用 Channel 写数据之前,建议使用 isWritable 方法来判断一下当前 ChannelOutboundBuffer 里的写缓存水位,防止 OOM 发生。

目录
相关文章
|
缓存 安全 API
RPC vs. HTTP:谁主沉浮在网络通信的江湖?
RPC vs. HTTP:谁主沉浮在网络通信的江湖?
1380 0
|
消息中间件 Java Apache
STOMP协议详解
STOMP协议详解 一、STOMP协议介绍 STOMP即Simple (or Streaming) Text Orientated Messaging Protocol,简单(流)文本定向消息协议,它提供了一个可互操作的连接格式,允许STOMP客户端与任意STOMP消息代理(Broker)进行交互。
6991 0
|
11月前
|
开发框架 前端开发 网络协议
Spring Boot结合Netty和WebSocket,实现后台向前端实时推送信息
【10月更文挑战第18天】 在现代互联网应用中,实时通信变得越来越重要。WebSocket作为一种在单个TCP连接上进行全双工通信的协议,为客户端和服务器之间的实时数据传输提供了一种高效的解决方案。Netty作为一个高性能、事件驱动的NIO框架,它基于Java NIO实现了异步和事件驱动的网络应用程序。Spring Boot是一个基于Spring框架的微服务开发框架,它提供了许多开箱即用的功能和简化配置的机制。本文将详细介绍如何使用Spring Boot集成Netty和WebSocket,实现后台向前端推送信息的功能。
2542 1
|
存储 数据安全/隐私保护
Netty实战(十三)WebSocket协议(一)
WebSocket 协议是完全重新设计的协议,旨在为 Web 上的双向数据传输问题提供一个切实可行的解决方案,使得客户端和服务器之间可以在任意时刻传输消息,因此,这也就要求它们异步地处理消息回执。
704 0
|
Java
“解密Netty中的BossGroup与WorkerGroup:他们之间的默契和配合“
“解密Netty中的BossGroup与WorkerGroup:他们之间的默契和配合“
1267 0
|
Java Maven
idea安装并使用maven依赖分析插件:Maven Helper
idea安装并使用maven依赖分析插件:Maven Helper
4038 7
|
缓存 监控 Java
Java中的内存泄漏及其排查方法
Java中的内存泄漏及其排查方法
|
编解码 分布式计算 网络协议
一文让你深入了解 Java-Netty高性能高并发
一文让你深入了解 Java-Netty高性能高并发
1180 1
|
存储 安全 Java
Netty实战(六)ChannelHandler和ChannelPipeline
ChannelHandler 的生命周期发生在ChannelHandler被添加到 ChannelPipeline 中或者被从 ChannelPipeline 中移除时。这些方法中的每一个都接受一个 ChannelHandlerContext 参数
441 0