一次 Netty 不健壮导致的无限重连分析

由于 OOM 导致不健壮的 Netty 一系列诡异的行为,这次的问题分析会比上次那个更有意思一点。(备注:本文 Netty 版本是上古时代的 3.7.0.Final)

现象描述

开发的同学反馈 dubbo 客户端无法调用远程的服务,抓包来看,客户端一直在建连,每次建连成功 3 秒以后就主动断开连接。

这个现象就很奇怪了,默认情况下 dubbo 消费端对属于同一个 provider 的不同 service 只会共享一条 tcp 连接进行通信,此处就是为了跟 provider 端建立这个连接。

为什么这里三次握手成功以后会断开连接呢?这个现象其实挺诡异的,于是想到用 strace 看一下背后到底发生了什么。

strace -f -T -p 238289 -o strace-new.238289.out

在 strace 中找 connect 相关的调用,根据线程号过滤对应的日志,可以看到发生了哪些系统调用:

一开始就创建一个 socket,将该套接字设置为非阻塞,随后调用 connect 发起建立,因为是非阻塞套接字,connect 这里不阻塞直接返回 -1,随后开始等待 3s,如果 3s 内没有能建立成功,futex 超时退出。

但是

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Netty WebSocket的重连,你可以采取以下步骤: 1. 创建一个WebSocket重连管理类,用于管理WebSocket的连接状态和重连逻辑。 2. 在WebSocket连接断开时,触发重连逻辑。你可以在`channelInactive`方法中检测连接断开事件。 3. 在重连逻辑中,使用`Bootstrap`重新建立WebSocket连接。你可以在重连方法中创建一个新的`WebSocketClientHandler`并添加到`Bootstrap`中。 4. 设置重连的时间间隔,避免频繁重连。可以使用定时器来触发重连逻辑,并设置一个合理的重连间隔时间。 5. 如果重连成功,更新连接状态并进行后续操作。如果重连失败,可以继续触发下一次重连。 下面是一个简单的示例代码,演示了如何实现Netty WebSocket的重连: ```java public class WebSocketReconnectManager { private final EventLoopGroup eventLoopGroup; private final String host; private final int port; private final URI uri; private Bootstrap bootstrap; private WebSocketClientHandler clientHandler; private ScheduledFuture<?> reconnectFuture; private boolean connected; public WebSocketReconnectManager(EventLoopGroup eventLoopGroup, String host, int port, String path) throws URISyntaxException { this.eventLoopGroup = eventLoopGroup; this.host = host; this.port = port; this.uri = new URI("ws://" + host + ":" + port + path); init(); } private void init() { bootstrap = new Bootstrap(); clientHandler = new WebSocketClientHandler(bootstrap, uri); bootstrap.group(eventLoopGroup) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new HttpClientCodec()); pipeline.addLast(new HttpObjectAggregator(8192)); pipeline.addLast(clientHandler); } }); connect(); } private void connect() { bootstrap.connect(host, port).addListener((ChannelFutureListener) future -> { if (future.isSuccess()) { connected = true; } else { connected = false; scheduleReconnect(); } }); } private void scheduleReconnect() { if (!connected && reconnectFuture == null) { reconnectFuture = eventLoopGroup.schedule(this::connect, 5, TimeUnit.SECONDS); } } public void onConnected() { connected = true; if (reconnectFuture != null) { reconnectFuture.cancel(false); reconnectFuture = null; } } public void onDisconnected() { connected = false; scheduleReconnect(); } } ``` 在你的WebSocket客户端代码中,需要在连接断开时调用`onDisconnected`方法,当重连成功后调用`onConnected`方法。这样就能实现简单的WebSocket重连逻辑。你可以根据自己的需求进行调整和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值