Kelvin的胡言乱语

==============> 重剑无锋,大巧不工。

Netty的使用及源代码阅读心得

记录一些关于netty使用以及源代码的阅读心得。

最新说明 :因为本人换了team,新team可能再也接触不到跟Java有关的东西了,而除了项目之外,本人也实在没有太多精力去再看nettty的源代码,所以,这一篇关于netty的心得可能到这里就不会再更新了 — <2013-03-27 Wed>

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。