Tcp Netty messageReceived()赢得';I don’我不会因为长期的联系而在一段时间后接到电话
最终编辑/结论 这是一个与netty无关的问题,仍然很难调试。messageReceived中的工作线程有时会被阻止,因此一段时间后池中没有可用线程 原始问题 在我的公司,我们使用netty来监听来自GPS跟踪设备的连接。跟踪器通过GPRS进行通信 我们在3.2.4决赛中经历了非常奇怪的表现 过了一段时间(我不能确切地说有多少,但将近一天),我们没有从追踪者那里得到任何信息。这意味着我们的SimpleChnneLupStreamHandler实现的messageReceived方法将不会被调用!但是,如果我使用tcpdump捕获所有数据包,我可以看到所有传入的消息 这是一个已知的问题,在netty的更高版本中已经修复了吗 我们的渠道管道如下所示:Tcp Netty messageReceived()赢得';I don’我不会因为长期的联系而在一段时间后接到电话,tcp,netty,gprs,Tcp,Netty,Gprs,最终编辑/结论 这是一个与netty无关的问题,仍然很难调试。messageReceived中的工作线程有时会被阻止,因此一段时间后池中没有可用线程 原始问题 在我的公司,我们使用netty来监听来自GPS跟踪设备的连接。跟踪器通过GPRS进行通信 我们在3.2.4决赛中经历了非常奇怪的表现 过了一段时间(我不能确切地说有多少,但将近一天),我们没有从追踪者那里得到任何信息。这意味着我们的SimpleChnneLupStreamHandler实现的messageReceived方法将不会被调用!
...
final TcpListenerChannelHandler tcpChannelHandler;
@Inject
public TcpListenerPipeline(TcpListenerChannelHandler tcpChannelHandler) {
this.tcpChannelHandler = tcpChannelHandler;
}
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline p = Channels.pipeline();
p.addLast("frameDecoder", new DelimiterBasedFrameDecoder(2048, Delimiters.lineDelimiter()));
p.addLast("encoder", new ByteArrayWrapperEncoder());
p.addLast("handler", tcpChannelHandler);
return p;
}
...
我们以以下方式实例化侦听:
public void startListen() {
ChannelFactory channelFactory = new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool(),20);
bootstrap = new ServerBootstrap(channelFactory);
bootstrap.setPipelineFactory(pipeline);
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.keepAlive", true);
lazyLogger.getLogger().info("Binding Tcp listener to 0.0.0.0 on port '{}'", listenPort);
serverChannel = bootstrap.bind(new InetSocketAddress("0.0.0.0", listenPort));
}
有人知道什么地方可能出错吗?或者我们应该每隔一小时左右手动断开所有通道
编辑:
我有关于这个问题的更多信息
如果未处理任何消息,也会发生在成功的远程连接上未调用channelConnected的情况。我远程调试了该问题,发现:
- 在NioServerSocketPipelineSink.java行#246 registerAcceptedChannel(acceptedSocket,currentThread);发生
- 软件执行一直到 DefaultChannelPipeline#781具有不同的事件,但我的TcpListenerChannelHandler从不在上下文中
public class TcpListenerChannelHandler extends SimpleChannelUpstreamHandler {
...
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
super.channelConnected(ctx, e);
_logger.info("{} device connected from: {}", deviceProtocol.getName(), ctx.getChannel().getRemoteAddress());
deviceConnectionRegistry.channelConnected(ctx.getChannel());
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
super.channelDisconnected(ctx, e);
_logger.info("{} device from endpoint '{}' disconnected.", deviceProtocol.getName(), ctx.getChannel().getRemoteAddress());
deviceConnectionRegistry.channelDisconnected(ctx.getChannel());
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent messageEvent) throws Exception {
super.messageReceived(ctx, messageEvent);
...
NOTE: here we process the meassage, I do not think it can cause any problem
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
if(_logger.isWarnEnabled())
_logger.warn(deviceProtocol.getName()+ " device"
+e.getChannel().getRemoteAddress()+" channel", e.getCause());
if (!(e.getCause() instanceof ConnectException))
e.getChannel().close();
}
与此同时,我已经升级到3.3.1-final。如果问题再次出现,我知道在哪里继续调试
编辑3:
我已经升级到3.3.1决赛,两天后同样的问题再次出现
我不知道它是否相关,但我们在同一物理接口上有更多的IP地址。我们是否应该尝试只在一个界面上侦听?更多eth接口是否存在任何已知问题
但同样:tcpdump识别跟踪程序的消息,但netty不调用自定义处理程序中的messageReceived
编辑4:
我进一步调试了代码。问题发生在niowerner.java
在第131行(boolean offered=registerTaskQueue.offer(registerTask);)运行正常,但任务将永远不会被处理。这意味着第748行的RegisterTask.run()将永远不会被调用 不知道,您是否尝试添加LoggingHandler来监视所有内容? 我使用自定义处理程序:
/**
*
* Adapted from the original LoggingHandler in Netty.
*/
public class LoggingHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler {
String name;
boolean hexDump;
public LoggingHandler(String name, boolean hexDump) {
this.name = name;
this.hexDump = hexDump;
}
/**
* Logs the specified event to the {@link InternalLogger} returned by
* {@link #getLogger()}. If hex dump has been enabled for this handler,
* the hex dump of the {@link ChannelBuffer} in a {@link MessageEvent} will
* be logged together.
*/
public void log(ChannelEvent e) {
String msg = name + " >> " + e.toString();
// Append hex dump if necessary.
if (hexDump && e instanceof MessageEvent) {
MessageEvent me = (MessageEvent) e;
if (me.getMessage() instanceof ChannelBuffer) {
ChannelBuffer buf = (ChannelBuffer) me.getMessage();
msg = msg + " - (HEXDUMP: " + ChannelBuffers.hexDump(buf) + ')';
}
}
// Log the message (and exception if available.)
if (e instanceof ExceptionEvent) {
Logger.debug(this, msg, ((ExceptionEvent) e).getCause());
} else {
Logger.debug(this, msg);
}
}
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
throws Exception {
log(e);
ctx.sendUpstream(e);
}
public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e)
throws Exception {
log(e);
ctx.sendDownstream(e);
}
wich同时插入客户端和服务器端。
在服务器端,我使用将其添加到子级和父级:
ChannelFactory factory = new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
ServerBootstrap bootstrap = new ServerBootstrap(factory);
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.keepAlive", true);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("LOGGER", new LoggingHandler("SERVER", true));
pipeline.addLast("LAUNCHER", handler.new OnChannelConnectedPlugger());
return pipeline;
}
});
bootstrap.setParentHandler(new LoggingHandler("SERVER-PARENT", true));
您可以包括您的自定义处理程序吗?我已经包括了TcpListenerChannelHandler的相关部分,这是唯一的自定义处理程序,这有帮助吗?感谢tipp,我将尝试添加一些日志记录!