Netty的使用及源代码阅读心得
记录一些关于netty使用以及源代码的阅读心得。
最新说明 :因为本人换了team,新team可能再也接触不到跟Java有关的东西了,而除了项目之外,本人也实在没有太多精力去再看nettty的源代码,所以,这一篇关于netty的心得可能到这里就不会再更新了 —
ChannelInitializer<C extends Channel>
这个类本身也是一个handler,主要关注 channel register
事件,关键方法如下:
public final void channelRegistered(ChannelHandlerContext ctx) throws Exception { boolean removed = false; boolean success = false; try { initChannel((C) ctx.channel()); ctx.pipeline().remove(this); removed = true; ctx.fireChannelRegistered(); success = true; } catch (Throwable t) { // ... } finally { // ... } }
注意其中的 initChannel(...)
方法调用,这个方法在这个类里定义为abstract,所以子类需要实现之,以进行channel的初始化,如添加handler等。
DefaultChannelHandlerContext中的Buffer Chain
DefaultChannelHandlerContext本身就是一系列context chain的一个结点,每个结点会维护prev和next两个指针,分别指向前后结点。
需要注意的是,这个context chain是双向的,在查找inbound的next buffer的时候,会顺着next指针朝前找;而查找outbound的next buffer的时候,会顺着prev指针朝回找。
每个context中,针对inbound和outbound都保留了两个类型的buffer引用:ByteBuf和MessageBuf,但是一个context只会有一种类型,这就要看当前的handler是下面的哪一种类型了:
- ChannelInboundByteHandler
- ChannelInboundMessageHandler
- ChannelOutboundByteHandler
- ChannelInboundMessageHandler
AttributeMap & attr()
Java NIO的SelectionKey中有一个attachment,这在传递一些额外的信息时很有用,Netty也有类似的实现,就是 AttributeMap
这个接口,其只定义了一个 attr()
方法。
DefaultAttributeMap
实现了这个接口,而 DefaultChannelHandlerContext
则继承了这个类,于是所有的Channel Context都可以附带额外信息了。attr()的实现如下:
public synchronized <T> Attribute<T> attr(AttributeKey<T> key) { Map<AttributeKey<?>, Attribute<?>> map = this.map; if (map == null) { // Not using ConcurrentHashMap due to high memory consumption. map = this.map = new IdentityHashMap<AttributeKey<?>, Attribute<?>>(2); } @SuppressWarnings("unchecked") Attribute<T> attr = (Attribute<T>) map.get(key); if (attr == null) { attr = new DefaultAttribute<T>(); map.put(key, attr); } return attr; }
可以看到,其内部是用了一个 IdentityHashMap
来保存key-value的信息,其key的类型是 AttributeKey<T>
,而value则是 Attribute<T>
。而这个 Attribute<T>
接口的实现如下(在DefaultAttributeMap的定义中):
private class DefaultAttribute<T> extends AtomicReference<T> implements Attribute<T> ...
而 AtomicReference<T>
则是java concurrent包中的类,Netty直接继承之以实现对象的get()/set()的并发访问。
注意 : ChannelHandlerContext和Channel都扩展了该接口,但Channel Handler Context只是针对于当前handler的Context,如果要将某些信息在不同的handler之间传递,需要设置Channel的attr。