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

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

核心概念的理解

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》

转载于:https://juejin.im/post/5a31d3475188257dd239a7d6

你可能感兴趣的文章
十四、转到 linux
查看>>
Got error 241 'Invalid schema
查看>>
男人要内在美,更要外在美
查看>>
为什么要跟别人比?
查看>>
app启动白屏
查看>>
Oracle 提高查询性能(基础)
查看>>
Hadoop集群完全分布式安装
查看>>
QString,char,string之间赋值
查看>>
我的友情链接
查看>>
Nginx+mysql+php-fpm负载均衡配置实例
查看>>
MySql之基于ssl安全连接的主从复制
查看>>
informix的逻辑日志和物理日志分析
查看>>
ARM inlinehook小结
查看>>
wordpress admin https + nginx反向代理配置
查看>>
管理/var/spool/clientmqueue/下的大文件
查看>>
centos 5.5 64 php imagick 模块错误处理记录
查看>>
apache中文url日志分析--php十六进制字符串转换
查看>>
浅谈代理
查看>>
基于jquery实现的超酷动画源码
查看>>
fl包下的TransitionManager的使用
查看>>