ChannelPipeline 负责channel数据进出处理,如数据编解码等。采用拦截思想设计,经过A handler处理后接着交给next handler

ChannelPipeline 并不是直接管理handler 而是通过 context 包装管理,一般以context 命名的是个重量级对象,提供给多层使用

public interface ChannelPipeline
extends ChannelInboundInvoker, ChannelOutboundInvoker, Iterable<Entry<String, ChannelHandler>> { //链表追加handler方法
ChannelPipeline addLast(String name, ChannelHandler handler);
ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler); ///////////////公开获取 ChannelHandler ChannelHandlerContext/////////////////
ChannelHandler first();
ChannelHandlerContext firstContext(); ChannelHandler last();
ChannelHandlerContext lastContext(); //省略部份代码..... ////////////////ChannelInboundInvoker接口的所有方法 统一返回 ChannelPipeline 对象//////////////////////
ChannelPipeline fireChannelRegistered();
ChannelPipeline fireChannelUnregistered();
ChannelPipeline fireChannelActive();
ChannelPipeline fireChannelInactive();
ChannelPipeline fireExceptionCaught(Throwable cause);
ChannelPipeline fireUserEventTriggered(Object event);
ChannelPipeline fireChannelRead(Object msg);
ChannelPipeline fireChannelReadComplete();
ChannelPipeline fireChannelWritabilityChanged();
ChannelPipeline flush(); ////////////////ChannelOutboundInvoker接口的所有方法 统一返回 ChannelFuture ChannelOutboundInvoker 对象//////////////////////
ChannelFuture bind(SocketAddress localAddress);
ChannelFuture connect(SocketAddress remoteAddress);
ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress);
ChannelFuture disconnect();
ChannelFuture close();
ChannelFuture deregister();
ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise);
ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise);
ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);
ChannelFuture disconnect(ChannelPromise promise);
ChannelFuture close(ChannelPromise promise);
ChannelFuture deregister(ChannelPromise promise);
ChannelOutboundInvoker read();
ChannelFuture write(Object msg);
ChannelFuture write(Object msg, ChannelPromise promise);
ChannelOutboundInvoker flush();
ChannelFuture writeAndFlush(Object msg, ChannelPromise promise);
ChannelFuture writeAndFlush(Object msg);
ChannelPromise newPromise();
ChannelProgressivePromise newProgressivePromise();
ChannelFuture newSucceededFuture();
ChannelFuture newFailedFuture(Throwable cause);
ChannelPromise voidPromise();
}

DefaultChannelPipeline实现做了代码整理,其中在添加handler时生成context由于代码比较简单不显示出来

public class DefaultChannelPipeline implements ChannelPipeline {
final AbstractChannelHandlerContext head;
final AbstractChannelHandlerContext tail; //绑定返回对象
private final Channel channel;
private final ChannelFuture succeededFuture;
private final VoidChannelPromise voidPromise; protected DefaultChannelPipeline(Channel channel) {
this.channel = ObjectUtil.checkNotNull(channel, "channel");
succeededFuture = new SucceededChannelFuture(channel, null);
voidPromise = new VoidChannelPromise(channel, true); tail = new TailContext(this);
head = new HeadContext(this); head.next = tail;
tail.prev = head;
} //双向链表追加,在tail之前插入
private void addLast0(AbstractChannelHandlerContext newCtx) {
AbstractChannelHandlerContext prev = tail.prev;
newCtx.prev = prev;
newCtx.next = tail;
prev.next = newCtx;
tail.prev = newCtx;
}
//双向链表删除
private static void remove0(AbstractChannelHandlerContext ctx) {
AbstractChannelHandlerContext prev = ctx.prev;
AbstractChannelHandlerContext next = ctx.next;
prev.next = next;
next.prev = prev;
} //HeadContext ChannelOutboundHandler出站操作通过Unsafe委托处理
final class HeadContext extends AbstractChannelHandlerContext
implements ChannelOutboundHandler, ChannelInboundHandler { private final Unsafe unsafe; HeadContext(DefaultChannelPipeline pipeline) {
super(pipeline, null, HEAD_NAME, false, true);
unsafe = pipeline.channel().unsafe();
setAddComplete();
} @Override
public void bind(
ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise)
throws Exception {
unsafe.bind(localAddress, promise);
} @Override
public void connect(
ChannelHandlerContext ctx,
SocketAddress remoteAddress, SocketAddress localAddress,
ChannelPromise promise) throws Exception {
unsafe.connect(remoteAddress, localAddress, promise);
} @Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
unsafe.write(msg, promise);
} @Override
public void flush(ChannelHandlerContext ctx) throws Exception {
unsafe.flush();
} @Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
invokeHandlerAddedIfNeeded();
ctx.fireChannelRegistered();
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.fireChannelRead(msg);
}
//......
}
} //ChannelHandlerContext 部份代码
//通过findContextInbound 查找下一个ctx 再通过ctx内部调用handler方法
@Override
public ChannelHandlerContext fireChannelRegistered() {
invokeChannelRegistered(findContextInbound());
return this;
} static void invokeChannelRegistered(final AbstractChannelHandlerContext next) {
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
next.invokeChannelRegistered();
} else {
executor.execute(new Runnable() {
@Override
public void run() {
next.invokeChannelRegistered();
}
});
}
} private void invokeChannelRegistered() {
if (invokeHandler()) {
try {
((ChannelInboundHandler) handler()).channelRegistered(this);
} catch (Throwable t) {
notifyHandlerException(t);
}
} else {
fireChannelRegistered();
}
}
//数据入站时从头到尾查找ctx
private AbstractChannelHandlerContext findContextInbound() {
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.next;
} while (!ctx.inbound);
return ctx;
}   //数据出站时从尾到头查找ctx
private AbstractChannelHandlerContext findContextOutbound() {
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.prev;
} while (!ctx.outbound);
return ctx;
}

小总:

1.从设计上可以看出,统一返回一个对象能减少大量的学习成本同开发成本

2.追加handler可以绑定一个线程组,在处理比较耗时的handler可以独立绑定线程组

3.从源码上看出:数据入站时如 channelRead(ChannelHandlerContext ctx, Object msg) 当处理完数据要手动执行next ctx action ctx.fireChannelRead(msg) 这点是比如奇怪的,如果开发者忘记调用了链表就断啦

4.DefaultChannelPipeline构造时默认生成head、tail,数据出站时操作顺序是tail ->linkHandler-> head,数据入站时是 head->linkHandler->tail

5.ChannelPipeline用到双向链表技术,大家在研发过程中可参考设计

[编织消息框架][netty源码分析]6 ChannelPipeline 实现类DefaultChannelPipeline职责与实现的更多相关文章

  1. [编织消息框架][netty源码分析]4 eventLoop 实现类NioEventLoop职责与实现

    NioEventLoop 是jdk nio多路处理实现同修复jdk nio的bug 1.NioEventLoop继承SingleThreadEventLoop 重用单线程处理 2.NioEventLo ...

  2. [编织消息框架][netty源码分析]11 ByteBuf 实现类UnpooledHeapByteBuf职责与实现

    每种ByteBuf都有相应的分配器ByteBufAllocator,类似工厂模式.我们先学习UnpooledHeapByteBuf与其对应的分配器UnpooledByteBufAllocator 如何 ...

  3. [编织消息框架][netty源码分析]5 eventLoop 实现类NioEventLoopGroup职责与实现

    分析NioEventLoopGroup最主有两个疑问 1.next work如何分配NioEventLoop 2.boss group 与child group 是如何协作运行的 从EventLoop ...

  4. [编织消息框架][netty源码分析]8 Channel 实现类NioSocketChannel职责与实现

    Unsafe是托委访问socket,那么Channel是直接提供给开发者使用的 Channel 主要有两个实现 NioServerSocketChannel同NioSocketChannel 致于其它 ...

  5. [编织消息框架][netty源码分析]9 Promise 实现类DefaultPromise职责与实现

    netty Future是基于jdk Future扩展,以监听完成任务触发执行Promise是对Future修改任务数据DefaultPromise是重要的模板类,其它不同类型实现基本是一层简单的包装 ...

  6. [编织消息框架][netty源码分析]5 EventLoopGroup 实现类NioEventLoopGroup职责与实现

    分析NioEventLoopGroup最主有两个疑问 1.next work如何分配NioEventLoop 2.boss group 与child group 是如何协作运行的 从EventLoop ...

  7. [编织消息框架][netty源码分析]7 Unsafe 实现类NioSocketChannelUnsafe职责与实现

    Unsafe 是channel的内部接口,从书写跟命名上看是不公开给开发者使用的,直到最后实现NioSocketChannelUnsafe也没有公开出去 public interface Channe ...

  8. [编织消息框架][netty源码分析]13 ByteBuf 实现类CompositeByteBuf职责与实现

    public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements Iterable<ByteBuf ...

  9. [编织消息框架][netty源码分析]3 EventLoop 实现类SingleThreadEventLoop职责与实现

    eventLoop是基于事件系统机制,主要技术由线程池同队列组成,是由生产/消费者模型设计,那么先搞清楚谁是生产者,消费者内容 SingleThreadEventLoop 实现 public abst ...

随机推荐

  1. EmpyoyeeManger_1.0

    整体结构 首先创建一个名为employee的数据库 create database employee; 然后在该数据库下建一张表 CREATE TABLE t_emp( id BIGINT PRIMA ...

  2. redis 主从配置实例、注意事项、及备份方式

    这两天在配置线上使用的redis服务.总得看起来,redis服务的配置文件还是非常简洁.清楚,配置起来非常顺畅,赞一下作者. 下面是我使用的配置,使用主从模式,在master上关掉所有持久化,在sla ...

  3. Ninja 之路:试炼!求生演习——异步 I/O、http

    鸣人火影之路的第一步,就是跟着卡卡西学习基本的忍术,让自己先在忍者的世界里生存下来,so,想要在 node 的世界里游刃有余,必须要掌握异步 I/O.http等核心技能. ok,第一步先学会读懂需求 ...

  4. java实现二叉树的构建以及3种遍历方法

    转载自http://ocaicai.iteye.com/blog/1047397 大二下学期学习数据结构的时候用C介绍过二叉树,但是当时热衷于java就没有怎么鸟二叉树,但是对二叉树的构建及遍历一直耿 ...

  5. .NET中webservice如何使用,调用

    webservice 只是"面向服务"编程的一种方式,现在把所有的方式都合在一起,就叫做WCF,,,,,, 1.创建 webservice服务,在web项目中添加"web ...

  6. 关于List<T> 的排序

    /** * @author hjn * @entity Student * @date 2017年5月23日15:22:18 */ public class Student { private Str ...

  7. $.when()方法翻译

    地址:http://api.jquery.com/jQuery.when/ jQuery.when( deferreds ),returns Promise 正文 Description: Provi ...

  8. Running R jobs quickly on many machines(转)

    As we demonstrated in “A gentle introduction to parallel computing in R” one of the great things abo ...

  9. GitBook 使用

    介绍 GitBook是一个基于Node.js的命令行工具,可使用 Github/Git和Markdown来制作精美的电子书,GitBook 并非关 Git的教程. 导出格式有PDF.HTML等,需要添 ...

  10. iphone手机中对于html和css的一些特殊处理

    1.iphone safari iso系统不兼容:hover的解决办法: 方法一: a:hover设置的样式在IOS系统的浏览器内显示不出来,看来是IOS系统的移动设备中,需要在按钮元素或者是body ...