博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于Netty的一些理解、实践与陷阱
阅读量:7073 次
发布时间:2019-06-28

本文共 2694 字,大约阅读时间需要 8 分钟。

核心概念的理解

Netty对于网络层进行了自己的抽象,用Channel表示连接,读写就是Channel上发生的事件,ChannelHandler用来处理这些事件,ChannelPipeline基于unix哲学提供了一种优雅的组织ChannelHandler的方式,用管道解耦不同层面的处理。现在回过头来看看,真的是非常天才和优雅的设计,是我心中API设计的典范之一了。

TCP半包、粘包

使用Netty内置的LineBasedFrameDecoder或者LengthFieldBasedFrameDecoder,我们只要在pipeline中添加,就解决了这个问题。

Writtable问题

有时候,由于TCP的send buffer满了,向channel的写入会失败。我们需要检查channel().isWritable()标记来确定是否执行写入。

处理耗时任务

Netty In Action以及网上的一些资料中,都没有很直接的展示如何在Netty中去处理耗时任务。其实也很简单,只要给handler指定一个事件循环就可以,例如

public class MyChannelInitializer extends ChannelInitializer
{ private static EventExecutorGroup longTaskGroup = new DefaultEventExecutorGroup(5); protected void initChannel(Channel channel) throws Exception { ChannelPipeline pipeline = channel.pipeline(); ... pipeline.addLast(longTaskGroup, new PrintHandler()); }}复制代码

Pitfall

Netty的ChannelPipeline只有一条双向链,消息入站,经过一串InBoundHandler之后,以相反的顺序再经过OutBoundHandler出站.因此,我们自定义的handler一般会处于pipeline的末尾!

举个例子,当以如下顺序添加handler时,如果调用ChannelHandlerContext上的writeAndFlush方法,出站消息是无法经过StringEncoder的

public class MyChannelInitializer extends ChannelInitializer
{ private static EventExecutorGroup longTaskGroup = new DefaultEventExecutorGroup(5); protected void initChannel(Channel channel) throws Exception { ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(new LineBasedFrameDecoder(64 * 1024)); pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast(longTaskGroup, new PrintHandler()); pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); }}复制代码

这个问题有两个解决方式

  1. 调整handler的顺序
  2. 调用channel上的writeAndFlush方法,强制使消息在整个pipeline上流动

调整handler的顺序

public class MyChannelInitializer extends ChannelInitializer
{ private static EventExecutorGroup longTaskGroup = new DefaultEventExecutorGroup(5); protected void initChannel(Channel channel) throws Exception { ChannelPipeline pipeline = channel.pipeline(); pipeline.addLast(new LineBasedFrameDecoder(64 * 1024)); pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); pipeline.addLast(longTaskGroup, new PrintHandler()); }}复制代码

调用Channel上的writeAndFlush方法

public class PrintHandler extends SimpleChannelInboundHandler
{ protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {// ctx.writeAndFlush(msg); ctx.channel().writeAndFlush(msg); System.out.println(msg); }}复制代码

参考

http://www.voidcn.com/article/p-yhpuvvkx-mm.html https://stackoverflow.com/questions/37474482/dealing-with-long-time-task-such-as-sql-query-in-netty 《Netty In Action》

转载地址:http://elkml.baihongyu.com/

你可能感兴趣的文章
解决 Nginx + PHP-FPM (Permission denied)报错的办法
查看>>
Cisco IPSec ××× 设计总结
查看>>
python excel 转 csv
查看>>
xmake 工程描述语法更新
查看>>
linux5.4 构建LAMP网站服务平台
查看>>
Cookie与Session的区别
查看>>
比传统事务快10倍?一张图读懂阿里云全局事务服务GTS
查看>>
FAQ_Zabbix:解决模板收集到的数据和真实数据有偏差
查看>>
有关游戏外挂的一些思考
查看>>
Bootstrap 介绍
查看>>
Python 的经典设计格言,格言来源于 Python 但不限于 Python
查看>>
python random模块
查看>>
数据流中的中位数(未)
查看>>
利用xss偷cookie教學
查看>>
CentOS 安装过程【图片】
查看>>
深入Hadoop节点部署的策略
查看>>
linux驱动编译常见错误记录
查看>>
Android设备路径及容量的读取
查看>>
Cocos2d-x3.0模版容器详解之三:cocos2d::Value
查看>>
Google已经获得www.baidu.com.sb域名
查看>>