netty 服务端向客户端推送大量数据,当服务端sendbuf 达到最高水位后(receivebuf空闲),不再继续推送数据,服务端sendbuf 却一直不下降,就卡在一个固定值了(64240),好像假死了,tcpdump 抓包 服务端能收到客户端的心跳数据,就是不能发送数据(服务netty channel iswriteble =false ,sendbuf 还是固定值)
查了下服务客户端的负载也在可接受的范围
netty 版本 4.1.66
服务端截图:
客户端截图:
下面是向客户端转发推送数据的代码片段:
@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());
}
}
看了你的描述后,推测是:
应用层写入数据的速度 > 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;
你看这个没用,服务端发送给客户端发送不了数据多半是代码问题
在底层网络来看就是客户端报告服务端我的滑动窗口满了.客户端没有进行recv操作.
你可以用tcpdump或者wireshark看看客户端的报告的自己滑动窗口值是多少.
服务端能收到客户端的心跳是因为服务端的滑动窗口是正常的,所以客户端可以send数据.如果服务端滑动窗口满了,客户端一样不能send
也有可能是客户端的窗口满了,客户端不能接受新的数据了,自然服务端就不能再向其发送了。
为啥我查看最后一张图片,也是第一张的呢?大家有遇到的么