用netty建立的长链接,在长链接过多,大批量发送数据的时候。发现好多消息发送失败,并且链接断开很多。
报错的的日志:
19:23:18.036 [nioEventLoopGroup-3-10] ERROR com.suning.live.service.MsgServiceImpl - chat msg 发送失败, msg is : {"content":"这是测试内容","fromCustNum":"test","fromHeadPic":"test","fromNickName":"test","level":1,"msgType":"text","session_id":"755069b917624224bdefd3a70c3d6c4b","toChatRoomId":"lyRoom","type":"Push2ChatRoom"} cause: java.nio.channels.ClosedChannelException: null
代码部分:
final Set<String> custNums = redisProcess.smembers(RedisKeys.ROOM_ID_KEY_PREFIXX + roomId); LOGGER.info("准备发送chat msg给client, 接收消息的custNum为 :" + custNums); if (null == custNums || custNums.size() <= 0) { return; } taskExecutor.execute(new Runnable() { @Override public void run() { for (String custNum : custNums) { sendMsgToCustNum(msg, custNum); } } });
private void sendMsgToCustNum(final String msg, String toCustNum) { try { Channel channel = channelStore.getChannel(toCustNum); if (null != channel && channel.isActive()) { channel.writeAndFlush(msg).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (!future.isSuccess()) { LOGGER.error("chat msg 发送失败, msg is : {} cause: ", msg, future.cause()); } } }); } } catch (Exception e) { LOGGER.error("chat msg 发送失败 wrapper, msg is : {}", e); } }
netty的链接关闭异常方法回调并没有进入。inactive channel的日志有打印 @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { LOGGER.error("Unexpected exception from downstream,channel" + ctx.channel() + " will be closed, exception is " + cause); // 当有异常时,关闭channel ctx.close(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { LOGGER.info("Channel " + ctx.channel() + " inactive."); // 删除channelGroup中的已关闭channel channelClosed(ctx); super.channelInactive(ctx); }
我之前用socket推消息的时候,也会报socketclosed的啥的错误。但我有重发机制。也就没打关心。
那个错误可能与你的网络带宽已用满有关。
你好,请问这个问题你解决了吗?
回复 @Super帅哥哥:我知道你的意思是判断客户端连接的合法性,这个我做了。但是这样不解决服务端并发问题。因为所有的客户端都是合法的。我现在困惑的是要切换服务器的时候,客户端的重连机制是3秒,到时候10万的客户端的话,每秒并发3万多上来,服务端是承受不了。这有办法解决吗?回复 @xiaoyaoweizi:socket对连接我感觉上是没有办法限制的,比如别人服务器正常开通了一个socket端口,我们一样可以用telnet连接测试,没法拒绝。但是我可以在他进行消息传输的时候进行判断是否是‘合法’链接,每个新连接进行建立的时候进行token校验,然后每次这个连接进行消息解码处理的时候判断下这个连接进行过token校验没。我个人任务回复 @Super帅哥哥:好的,我去测试一下,我还有一个问题,netty如何限流防止高并发呢?场景假设服务端连接10万台的客户端,当服务端崩溃重启后,10客户端大量连接上来,怎么在netty层进行socket限流呢?回复 @xiaoyaoweizi:具体原因可能有所不同,要看现场情况。排除的时候,你可以将超时处理关掉再压测,如果没问题,说明就是这个情况了。至于我的那个问题原因,是因为客户端发送超时,调度连接池因为处理不过来到延迟发送超,超过了服务端设置的READER_IDLE值回复 @Super帅哥哥:你的意思是压力测试时,客户端的心跳发送会超时,还是服务端处理心跳包时超时?我也是在做压力测试,跑了12万的客户端,每隔60s发一次心跳包和一次数据。跑了6万多时,大量报出这个错误。版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。