netty原始碼分析一
阿新 • • 發佈:2021-10-30
一個channel對應一個pipeline,pipeline是channel的成員變數,初始化channel的時候就初始化了pipeline,一個pipeline裡面包含多個handler,其中在初始化handler的時候,會同時初始化head/tail兩個handlerContext;一個DefaultChannelHandlerContext
裡面包含一個handler,換句話說handler是以handlerContext
的形式存在。
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel { private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractChannel.class); private final Channel parent; // 代表父類channel private final ChannelId id; // 採用預設方式生成的全域性唯一id //實現具體的連線與讀/寫資料,如網路的讀/寫、鏈路關閉、發起連線等 private final Unsafe unsafe; // Unsafe例項 //一個Handler的容器,也可以將其理解為一個Handler鏈。Handler主要處理資料的編/解碼和業務邏輯。 private final DefaultChannelPipeline pipeline; // 當前channel對應的DefaultChannelPipeline private final VoidChannelPromise unsafeVoidPromise = new VoidChannelPromise(this, false); private final CloseFuture closeFuture = new CloseFuture(this); private volatile SocketAddress localAddress; private volatile SocketAddress remoteAddress; private volatile EventLoop eventLoop; // 當前channel註冊的EventLoop 每個Channel對應一條EventLoop執行緒。 private volatile boolean registered; private boolean closeInitiated; private Throwable initialCloseCause; /** * Cache for the string representation of this channel */ private boolean strValActive; private String strVal; /** * Creates a new instance. * * @param parent the parent of this channel. {@code null} if there's no parent. */ protected AbstractChannel(Channel parent) { this.parent = parent; id = newId(); unsafe = newUnsafe(); pipeline = newChannelPipeline(); // 建立pipeline } }
下面是pipeline的具體實現類,可以看到在初始化pipeline的時候,也初始化了head/tail兩個變數, 同時改變了指向
public class DefaultChannelPipeline implements ChannelPipeline { // pipeline裡面 final AbstractChannelHandlerContext head; final AbstractChannelHandlerContext tail; private final Channel channel; private final ChannelFuture succeededFuture; private final VoidChannelPromise voidPromise; private final boolean touch = ResourceLeakDetector.isEnabled(); private boolean registered; protected DefaultChannelPipeline(Channel channel) { this.channel = ObjectUtil.checkNotNull(channel, "channel");// 這個方法值得借鑑 succeededFuture = new SucceededChannelFuture(channel, null); voidPromise = new VoidChannelPromise(channel, true); // 建立兩個節點 tail = new TailContext(this); //AbstractChannelHandlerContext head = new HeadContext(this); //AbstractChannelHandlerContext的子類 head.next = tail; tail.prev = head; } }
pipeline裡面儲存著連結串列的頭結點和尾節點,因為很容易向連結串列中新增元素,具體方法如下:
// 這個方法向連結串列裡面新增節點 private void addLast0(AbstractChannelHandlerContext newCtx) { AbstractChannelHandlerContext prev = tail.prev; newCtx.prev = prev; newCtx.next = tail; prev.next = newCtx; tail.prev = newCtx; }
在執行handler的過程中需要一個一個的遍歷連結串列,具體方法如下:
private AbstractChannelHandlerContext findContextInbound(int mask) {// 這個是從連結串列裡面獲取一個元素 那麼是怎麼新增進去的呢?這個方法見上面
logger.info("findContextInbound-_-");
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.next;
} while ((ctx.executionMask & mask) == 0);
return ctx;
}