gpt4 book ai didi

java - 为什么 Netty 客户端表现得像僵尸?

转载 作者:行者123 更新时间:2023-11-30 07:39:09 24 4
gpt4 key购买 nike

我使用netty作为套接字客户端:

public void run() {
isRunning = true;
EventLoopGroup group = new NioEventLoopGroup(EventLoopsPerGetter);
Bootstrap b = new Bootstrap();
b.group(group).channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {

@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(
new ProtobufVarint32FrameDecoder(),
ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP),
new ProtobufDecoder(Protocol.Packet.getDefaultInstance()),

new ProtobufVarint32LengthFieldPrepender(),
ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP),
new ProtobufEncoder(),

session
);
}
});
try {
while(isRunning) {
try {
b.connect(host, port).sync().channel().closeFuture().sync();
} catch(Exception e) {
if (e instanceof InterruptedException) {
throw e;
}
retryLogger.warn("try to connect to " + host + " : " + port + " , but", e);
}
if(isRunning) {
retryLogger.info("netty connection lost, retry!");
Thread.sleep(RetryInterval);
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
group.shutdownGracefully();
}
}

session 代码非常简单,发送Get-packet到服务器,获取响应,写入文件,然后发送下一个Get-packet。

在这个程序中,我启动了两个netty客户端线程,但是运行几天后,其中一个线程的行为就像僵尸线程,也就是说,即使我杀死netty服务器,僵尸客户端也不会打印任何日志,而另一个客户端则不会打印任何日志打印想要的日志。顺便说一句,jstack 文件显示两个线程都处于 Activity 状态,而不是死亡状态。

我使用的是netty 5。

最佳答案

您没有任何读取超时机制,发生的情况是 10~(取决于路由器型号)分钟内没有流量,并且路由器中的 NAT 表认为连接已完成,并关闭连接.

您有多种方法可以解决此问题:

使用ReadTimeoutHandler

ReadTimeoutHandler 关闭 channel 并抛出 ReadTimeoutException如果检测到超时。如果需要,您可以通过exceptionCaught捕获此异常。 。根据您现有的逻辑,您不需要捕捉到这一点。

此处理程序还可以与 WriteTimeoutHandler 结合使用将“ping”消息写入远程。然而,以下解决方案更适合此目的。

使用IdleStateHandler

您还可以使用 IdleStateHandler 来实现此目的,该处理程序有 3 个参数,分别代表 readerIdleTimewriteIdleTimeallIdleTime 。该类的优点是不会抛出异常,并且使用Netty userEventTriggered调度它的调用,虽然这使得类更难使用,但您可以用它做更多的事情。

例如,如果您的协议(protocol)支持 ping 消息,则可以使用此类来发送这些 ping 消息。使用此类非常容易,并且可以在处理程序中使用,如下所示:

public class MyChannelInitializer extends ChannelInitializer<Channel> {
@Override
public void initChannel(Channel channel) {
channel.pipeline().addLast("idleStateHandler", new IdleStateHandler(60, 30, 0));
channel.pipeline().addLast("myHandler", new MyHandler());
}
}

// Handler should handle the IdleStateEvent triggered by IdleStateHandler.
public class MyHandler extends ChannelHandlerAdapter {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent e = (IdleStateEvent) evt;
if (e.state() == IdleState.READER_IDLE) {
ctx.close();
} else if (e.state() == IdleState.WRITER_IDLE) {
ctx.writeAndFlush(new PingMessage());
}
}
}
}

关于java - 为什么 Netty 客户端表现得像僵尸?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34942511/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com