wangyingfa 2021-10-10 13:02 采纳率: 0%
浏览 2776
已结题

netty 服务端推送sendBuf 满了后 一直阻塞 不会减少

netty 服务端向客户端推送大量数据,当服务端sendbuf 达到最高水位后(receivebuf空闲),不再继续推送数据,服务端sendbuf 却一直不下降,就卡在一个固定值了(64240),好像假死了,tcpdump 抓包 服务端能收到客户端的心跳数据,就是不能发送数据(服务netty channel iswriteble =false ,sendbuf 还是固定值)

查了下服务客户端的负载也在可接受的范围
netty 版本 4.1.66
服务端截图:

img

客户端截图:

img

下面是向客户端转发推送数据的代码片段:
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {

    Channel channel = ctx.channel();
    ProxyChannel userChannel=GlobalChannelGroup.getUserChannelByDispatcherShortId(channel.id().asShortText());
    Channel uc=userChannel.getChannel();
    if(uc!=null) {
      if(uc.isWritable()&&uc.isActive()) {
        try {
          //ChannelFuture  future=uc.writeAndFlush(msg);
          ChannelFuture  future= uc.writeAndFlush(safeDuplicate(msg));
          future.addListener((future1 -> {
            if (future1.isSuccess()) {
              LOGGER.info("代理-转发-成功-代:{}-用:{}-代:{}-用:{}",channel.id().asShortText(),uc.id().asShortText(),channel.remoteAddress(),uc.remoteAddress());
          } else {
              LOGGER.info("代理-转发-失败-代:{}-用:{}-代:{}-用:{}-{}--{}",channel.id().asShortText(),uc.id().asShortText(),channel.remoteAddress(),uc.remoteAddress(),uc.isActive(),future1.cause());
          }
         }));
          
        }finally{
          //LOGGER.info("-------------------------------------------V1");
        }
        
      }else {
        LOGGER.warn("channel:{},缓存已满-距离需消耗:{}--代理:{}-用户:{}", uc.id().asShortText(), uc.bytesBeforeWritable(),channel.remoteAddress(),uc.remoteAddress());
      }
    }else {
        LOGGER.info("获取用户链接不存在-或已经关闭---{}",channel.id().asShortText());
    }
}

img

img

img

img

  • 写回答

4条回答 默认 最新

  • 墨渧 2021-10-11 18:38
    关注

    看了你的描述后,推测是:
    应用层写入数据的速度 > Socket的发送速度,导致ChannelOutboundBuffer无界的链表不断增长,超出了ChannelOutboundBuffer高水位设定阈值,当ChannelOutboundBuffer的容量超过高水位设定阈值后,isWritable()返回false。
    解决办法:
    1)更换网络环境(硬件、软件等),使用高速网络,提高Socket的发送速度
    2)降低应用层写入数据的速度;
    3)更改ChannelOutboundBuffer水位设定阈值->.option(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, 64 * 1024),短时间内能解决“isWritable()返回false”的问题,但是,如果应用层写入数据的速度 > Socket的发送速度,最终还是会造成数据积压,最后isWritable()还是会返回false,并且此操作容易产生OOM;

    评论

报告相同问题?

问题事件

  • 请采纳用户回复 10月21日
  • 系统已结题 10月18日
  • 修改了问题 10月11日
  • 修改了问题 10月11日
  • 展开全部

悬赏问题

  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图