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。