在Netty中每个Channel都有且仅有一个ChannelPipeline与之对应,而每个ChannelPipeline中又维护了一个由ChannelHandlerContext组成的双向链表,链表头是HeadContext,链表尾是TailContext,并且每个ChannelHandlerContext中又关联着一个ChannelHandler,如图示:
每个Channel都会有一个相应的ChannelPipeline:
protected AbstractChannel(Channel parent) {
this.parent = parent;
unsafe = newUnsafe();
pipeline = new DefaultChannelPipeline(this);
}
这里代码是AbstractChannel构造器,在构造器中会初始化他为DefaultChannelPipeline的实例,这里的代码就印证了每个Channel都会有一个相应的ChannelPipeline的观点。
io.netty.channel.DefaultChannelPipeline,DefaultChannelPipeline是ChannelPipeline的实现类。
接下来看DefaultChannelPipeline的初始化过程:
public DefaultChannelPipeline(AbstractChannel channel) {
if (channel == null) {
throw new NullPointerException("channel");
}
this.channel = channel;
tail = new TailContext(this);
head = new HeadContext(this);
head.next = tail;
tail.prev = head;
}
这里首先将与其关联的Channel保存到字段channel中,接着实例化两个ChannelHandlerContext,HeadContext与TailContext构成双向链表,这里HeadContext和TailContext继承于AbstractChannelHandlerContext的同时也实现了ChannelHandler接口,所以他们有Context和Handler的双重属性。
在pipeline内添加节点是在是在这两点中间添加context,链表头尾依旧是这两个。
ChannelPipeline上相关方法,addFirst、addBefore、addAfter、addLast都是将一个ChannelHandler添加到ChannelPipeline中。
这里只看addLast方法的具体实现:
addLast(EventExecutorGroup group, String name, ChannelHandler handler) 方法,添加一个 ChannelHandler 对象到 pipeline 中:
@Override
@SuppressWarnings("Duplicates")
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
final AbstractChannelHandlerContext newCtx;
synchronized (this) {
// 同步,为了防止多线程并发操作 pipeline 底层的双向链表
// 检查是否有重复 handler
checkMultiplicity(handler);
// 创建节点名 调用filterName()方法获取ChannelHandler名字
// 创建节点 调用newContext()方法创建DefaultChannelHandlerContext节点
newCtx = newContext(group, filterName(name, handler), handler);
// 添加到最后一个节点
addLast0(newCtx);
// If the registered is false it means that the channel was not registered on an eventloop yet.
// In this case we add the context to the pipeline and add a task that will call
// ChannelHandler.handlerAdded(...) once the channel is registered.
if (!registered) {
// 设置 AbstractChannelHandlerContext 准备添加中
newCtx.setAddPending();
// 添加 PendingHandlerCallback 回调
callHandlerCallbackLater(newCtx, true);
return this;
}
// 不在 EventLoop 的线程中,提交 EventLoop 中,执行回调用户方法
EventExecutor executor = newCtx.executor();
if (!executor.inEventLoop()) {
// 设置 AbstractChannelHandlerContext 准备添加中,即就是设置状态为准备添加
newCtx.setAddPending();
// 提交 EventLoop 中,执行回调 ChannelHandler added 事件
executor.execute(new Runnable() {
@Override
public void run() {
callHandlerAdded0(newCtx);
}
});
return this;
}
}
// 回调 ChannelHandler added 事件
callHandlerAdded0(newCtx);
return this;
}
private String filterName(String name, ChannelHandler handler) {
if (name == null) {
//如果没有传入默认的名字,则调用generateName方法,根据ChannelHandler生成一个唯一的名字。
return generateName(handler);
}
//如果已经传入默认的名字则调用checkDuplicateName()方法检验名字唯一性
checkDuplicateName(name); // <2>
return name;
}
private String generateName(ChannelHandler handler) {
// 从缓存中查询,是否已经生成默认名字
Map<Class<?>, String> cache = nameCaches.get();
Class<?> handlerType = handler.getClass();
String name = cache.get(handlerType);
// 若未生成过,进行生成
if (name == null) {
name = generateName0(handlerType);
cache.put(handlerType, name);
}
// 判断是否存在相同名字的节点
// It's not very likely for a user to put more than one handler of the same type, but make sure to avoid
// any name conflicts. Note that we don't cache the names generated here.
if (context0(name) != null) {
// 若存在,则使用基础名字 + 编号,循环生成,直到一个是唯一的
String baseName = name.substring(0, name.length() - 1); // Strip the trailing '0'.
for (int i = 1;; i ++) {
String newName = baseName + i;
if (context0(newName) == null) {
// // 判断是否存在相同名字的节点
name = newName;
break;
}
}
}
return name;
}
private AbstractChannelHandlerContext context0(String name) {
AbstractChannelHandlerContext context = head.next;
// 顺序向下遍历节点,判断是否有指定名字的节点。如果有,则返回该节点。
while (context != tail) {
if (context.name().equals(name)) {
return context;
}
context = context.next;
}
return null;
}
private void checkDuplicateName(String name) {
if (context0(name) != null) {
// 如果存在节点就说明不唯一,抛异常
throw new IllegalArgumentException("Duplicate handler name: " + name);
}
}
private AbstractChannelHandlerContext newContext(EventExecutorGroup group, String name, ChannelHandler handler) {
return new DefaultChannelHandlerContext(this, childExecutor(group) , name, handler);
}
private EventExecutor childExecutor(EventExecutorGroup group) {
//一般情况下是这个:
// 不创建子执行器
if (group == null) {
return null;
}
// 根据配置项 SINGLE_EVENTEXECUTOR_PER_GROUP ,每个 Channel 从 EventExecutorGroup 获得不同 EventExecutor 执行器
Boolean pinEventExecutor = channel.config().getOption(ChannelOption.SINGLE_EVENTEXECUTOR_PER_GROUP);
if (pinEventExecutor != null && !pinEventExecutor) {
return group.next();
}
// 通过 childExecutors 缓存实现,一个 Channel 从 EventExecutorGroup 获得相同 EventExecutor 执行器
Map<EventExecutorGroup, EventExecutor> childExecutors = this.childExecutors;
if (childExecutors == null) {
// Use size of 4 as most people only use one extra EventExecutor.
childExecutors = this.childExecutors = new IdentityHashMap<EventExecutorGroup, EventExecutor>(4);
}
// Pin one of the child executors once and remember it so that the same child executor
// is used to fire events for the same channel.
EventExecutor childExecutor = childExecutors.get(group);
// 缓存不存在,进行 从 EventExecutorGroup 获得 EventExecutor 执行器
if (childExecutor == null) {
childExecutor = group.next();
childExecutors.put(group, childExecutor); // 进行缓存
}
return childExecutor;
}
private void addLast0(AbstractChannelHandlerContext newCtx) {
// 获得 tail 节点的前一个节点
AbstractChannelHandlerContext prev = tail.prev;
// 新节点,指向 prev 和 tail 节点
newCtx.prev = prev;
newCtx.next = tail;
// 在 prev 和 tail ,指向新节点
prev.next = newCtx;
tail.prev = newCtx;
}
private void callHandlerAdded0(final AbstractChannelHandlerContext ctx) {
try {
// We must call setAddComplete before calling handlerAdded. Otherwise if the handlerAdded method generates
// any pipeline events ctx.handler() will miss them because the state will not allow it.
// 设置 AbstractChannelHandlerContext 已添加
ctx.setAddComplete();
// 回调 ChannelHandler 添加完成( added )事件
//一般来说通过这个方法来初始化ChannelHandler,由于这个方法的在EventLoop的线程中执行,所以要尽量避免执行时间过长。
ctx.handler().handlerAdded(ctx);
} catch (Throwable t) {
// 发生异常,移除该节点
boolean removed = false;
try {
remove0(ctx); // 移除
try {
ctx.handler().handlerRemoved(ctx);
// 回调 ChannelHandler 移除完成( removed )事件
} finally {
ctx.setRemoved(); // 标记节点已移除
}
removed = true; // 标记移除成功
} catch (Throwable t2) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to remove a handler: " + ctx.name(), t2);
}
}
// 触发异常的传播
if (removed) {
fireExceptionCaught(new ChannelPipelineException(
ctx.handler().getClass().getName() +
".handlerAdded() has thrown an exception; removed.", t));
} else {
fireExceptionCaught(new ChannelPipelineException(
ctx.handler().getClass().getName() +
".handlerAdded() has thrown an exception; also failed to remove.", t));
}
}
}
addLast(ChannelHandler… handlers) 添加任意数量的ChannelHandler对象:
调用addLast(executor, null, h); 添加一个ChannelHandler对象到pipeline
@Override
public final ChannelPipeline addLast(ChannelHandler... handlers) {
return addLast(null, handlers);
}
@Override
public final ChannelPipeline addLast(EventExecutorGroup executor, ChannelHandler... handlers) {
if (handlers == null) {
throw new NullPointerException("handlers");
}
for (ChannelHandler h: handlers) {
if (h == null) {
break;
}
addLast(executor, null, h);
//添加一个ChannelHandler对象到pipeline
}
return this;
}
添加部分就先看这些。