zl程序教程

您现在的位置是:首页 >  其它

当前栏目

Netty

Netty
2023-09-27 14:24:04 时间

ChannelInboundHandlerAdapter#channelRead 中如果通过 ChannelHandlerContext#writeAndFlush 发送多条消息的话,消息都是在处理完之后,一起 flush 出去的。
如果想要实现每隔一段时间,发送一条消息这种需求的话,可以另起一个 schdule 线程,定时去发送消息。

场景:接收到任务开始消息后,每隔2s上报一次任务状态,上报10次后,发送一个任务结束消息
两种方式实现:
1. 接收到任务开始消息后,启一个 schdule 线程,每隔 2s 上报一次任务状态,上报到第 10 次的时候,在任务状态消息中打个任务结束标记
当客户端接收到服务端处理任务状态消息的回包后,发现任务结束标记后,就发送任务结束消息
注:这种方式要求客户端和服务端在收发消息时将任务结束标记在一来一回的传递中原样传递

2. 接收到任务开始消息后,启一个 schdule 线程,每隔 2s 上报一次任务状态,上报到第 10 次的时候,发送任务结束消息

错误的做法1:在 ChannelHandler 线程中每隔 2s 上报一次消息,这样消息会在最后一次才全部 flush。
错误的做法2:在 ChannelHandler 线程中启一个 schdule 线程,每隔 2s 上报一次任务状态。同时在 ChannelHandler 线程中监听任务状态上报是否结束,没有结束就 sleep,直到上报完成再发送任务结束消息
这两种做法错误的原因在于: ChannelHandler 线程在发送消息的过程中阻塞了,所以所有的消息都是在整个逻辑处理完之后再 flush 出去的

排查netty错误时,可以将 netty 的日志开启:
//记录请求与响应报文
InternalLoggerFactory.setDefaultFactory(Slf4JLoggerFactory.INSTANCE);
pipeline.addAfter("idleEventHandler","loggingHandler",new LoggingHandler(LogLevel.INFO));

这样就会得到类似如下的日志,这样就可以清楚的看到 netty wirte、read、flush的日志了:

 

推荐:
https://www.infoq.cn/article/netty-high-performance/