注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

小葫芦君(汉斯的博客)

博客迁移到新博客:https://blog.ssxingshou.com

 
 
 

日志

 
 
关于我

小小葫芦商城,为您提供高品质的商品,一流的产品,一流的包装服务,一流的物流服务,放心购买

网易考拉推荐

Netty 4.0 新的特性及需要注意的地方 3  

2014-04-11 21:52:24|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

每个处理器的缓存

不像3.x那样在每次读操作都简历一个新堆里的缓存来触发上游的MessageEvent,4.0不会每次都创建新的 缓存。它直接从socket中读取数据到由用户的ChannelInboundByteHandler和ChannelInboundMessageHandler实现创建的入站缓存。

因为由上述处理器创建的入站缓存直到关联的通道关闭前都会重用,所以在上面的GC和内存带宽消耗都能保持较小。同样,当接收到的数据被销毁时用户已经完成操作,codec的实现就变得更简单和有效了

在创建出站缓存时也是差不多的(不会新建)。用户的ChannelOutBoundBYteHandler和ChannelOutboundMessageHandler来操作。

不需要每条消息都有一个事件

4.0里不再有了messageReceived或writeRequested处理器方法。它们被inboundBufferUpdated和flush代替了。用户的入队一个或多个消息到一个入站(或出站)缓存同时会出发一个inboundBUfferUpdated(或flush)事件。

01public void inboundBufferUpdated(ChannelHandlerContext ctx) {
02    Queue<MyMessage> in = ctx.inboundMessageBuffer();
03    Queue<MyNewMessage> out = ctx.nextInboundMessageBuffer();
04    for (;;) {
05        MyMessage m = in.poll();
06        if (m == null) {
07            break;
08        }
09        MyNewMessage decoded = decode(m);
10        out.add(decoded);
11    }
12    ctx.fireInboundBufferUpdated();
13}
14 
15public void flush(ChannelHandlerContext ctx, ChannelFuture future) {
16    Queue<MyNewMessage> in = ctx.outboundMessageBuffer();
17    Queue<MyMessage> out = ctx.nextOutboundMessageBuffer();
18    for (;;) {
19        MyNewMessage m = in.poll();
20        if (m == null) {
21            break;
22        }
23        MyMessage encoded = encode(m);
24        out.add(encoded);
25    }
26    ctx.flush(future);
27}

作为选择,用户能够在每个单独的入站(或出站)消息中触发这样的事件来模拟老的行为,尽管相对新方法来说效率更低。

消息处理器 vs. 字节处理器

在3.x里一个MessageEvent持有一个任意的对象。它能够是一个ChannelBuffer或是一个用户自定义的对象,它们都是同样对待的:

01@Override
02public void messageReceived(ChannelHandlerContext ctx, MessageEvent evt) {
03    Object msg = evt.getMessage();
04    if (msg instanceof ChannelBuffer) {
05        ChannelBuffer buf = (ChannelBuffer) msg;
06        ...
07    else {
08        MyMessage myMsg = (MyMessage) msg;
09        ...
10    }
11}

在4.0里,它们就分别对待了,因为一个处理器不再处理一个独立的消息,而是处理多种多样的消息:

01public void inboundBufferUpdated(ChannelHandlerContext ctx) {
02    if (ctx.hasInboundByteBuffer()) {
03        ByteBuf buf = ctx.inboundByteBuffer();
04        ...
05    else {
06        Queue<MyMessage> buf = ctx.inboundMessageBuffer();
07        for (;;) {
08            MyMessage msg = buf.poll();
09            if (buf == null) {
10                break;
11            }
12            ...
13        }
14    }
15}

你可能发现一个ServerChannel的处理器是一个入站缓存是Queue<Channel>的入站处理器是较为有趣的。

处理器适配器

大多数用户都发现创建和管理它的生命周期是繁琐的,因此它支持用户扩展预定义好的适配器类来使得更方便:

  • ChannelHandlerAdapter
  • ChannelStateHandlerAdapter
  • ChannelOperationHandlerAdapter
  • ChannelInboundMessageHandlerAdapter
  • ChannelInboundByteHandlerAdapter
  • ChannelOutboundMessageHandlerAdapter
  • ChannelOutboundByteHandlerAdapter

    明智的和不易出错的入站流量挂起

    3.x有一个由Channel.setReadable(boolean)提供的不是很明显的入站流量挂起机制。它引入了在ChannelHandler之间的复杂交互操作,同时处理器由于不正确实现而很容易互相干扰。

    4.0里,新的名为read()的出站操作增加了。如果你使用Channel.config().setAutoRead(false)来关闭默认的auto-read标志,Netty不会读入任何东西,直到你显式地调用read()操作。一旦你发布的read()操作完成,同时通道再次停止读,一个名为channelReadSuspended()的入站事件会触发一遍你能够重新发布另外的read()操作。你同样也可以拦截read()操作来执行更多高级的流量控制。

    暂停接收传入的连接

    在3.x里,没有方法让一个用户告诉Netty来厅子接收传入连接,除非是阻塞I/O线程或者关闭服务器socket。在aotu-read标志没有设置的时候,4.0涉及到的read()操作就像一个普通的通道。

  评论这张
 
阅读(449)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017