[netty5笔记-总体流程分析3-ChannelHandlerContext](http://blog.csdn.net/youaremoon/article/details/50449867)
[Netty4学习笔记(1)-- ChannelPipeline](http://blog.csdn.net/zxhoo/article/details/17264263)
处理链处理写操作流程、Pipeline,Context和Handler的协作处理。
netty核心的概念:Channel、Buffer、Selecter
## Channel
Channel是核心的一个接口,表示一个联络Socket的通道。通过Channel,可以对Socket进行各种操作。
## ChannelHandler
在实际程序实现中,很少直接操作Channel,而是通过ChannelHandler来间接操纵Channel。(使用策略模式?)
### ChannelHandler的种类:
ChannelHandler接口的子接口
- ChannelInboundHandler
- ChannelOutboundHandler
> 5.0.0.Alpha1 版本已经没有了这两个接口,why。4.1.5存在。
## ChannelPipeline
ChannelPipeline里有一个双向链表,使用HashMap存放节点。节点类型为:ChannelHandlerContext。
是一个ChandlerHandler的链表。当需要对Channel进行某种处理的时候,Pipeline负责依次调用每一个Handler进行处理。(责任链模式?)
> 每个Channel都有一个属于自己的Pipeline.(一对一关系)
ChannelPipeline的方法有很多,其中一部分是用来管理ChannelHandler的,如下面这些:
```
ChannelPipeline addFirst(String name, ChannelHandler handler);
ChannelPipeline addLast(String name, ChannelHandler handler);
ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler);
ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler);
ChannelPipeline remove(ChannelHandler handler);
ChannelHandler remove(String name);
ChannelHandler removeFirst();
ChannelHandler removeLast();
ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);
ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler);
ChannelHandler first();
ChannelHandler last();
ChannelHandler get(String name);
```
### 事件的传播
为了搞清楚事件如何在Pipeline里传播,
- 让我们从Channel的抽象子类AbstractChannel开始:
```
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
// ...
@Override
public Channel write(Object msg) {
return pipeline.write(msg);
}
// ...
}
```
- 再看DefaultChannelPipeline的write()方法实现
```
final class DefaultChannelPipeline implements ChannelPipeline {
// ...
@Override
public ChannelFuture write(Object msg) {
return tail.write(msg);
}
// ...
}
```
因为write是个outbound事件,所以DefaultChannelPipeline直接找到tail部分的context,调用其write()方法
- 接着看DefaultChannelHandlerContext的write()方法
```
final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {
// ...
@Override
public ChannelFuture write(Object msg) {
return write(msg, newPromise());
}
@Override
public ChannelFuture write(final Object msg, final ChannelPromise promise) {
if (msg == null) {
throw new NullPointerException("msg");
}
validatePromise(promise, true);
write(msg, false, promise);
return promise;
}
private void write(Object msg, boolean flush, ChannelPromise promise) {
DefaultChannelHandlerContext next = findContextOutbound();
next.invokeWrite(msg, promise);
if (flush) {
next.invokeFlush();
}
}
private DefaultChannelHandlerContext findContextOutbound() {
DefaultChannelHandlerContext ctx = this;
do {
ctx = ctx.prev;
} while (!ctx.outbound);
return ctx;
}
private void invokeWrite(Object msg, ChannelPromise promise) {
try {
((ChannelOutboundHandler) handler).write(this, msg, promise);
} catch (Throwable t) {
notifyOutboundHandlerException(t, promise);
}
}
// ...
}
```
context的write()方法沿着context链往前找,直至找到一个outbound类型的context为止,然后调用其invokeWrite()方法
invokeWrite()接着调用handler的write()方法:
## ChannelHandlerContext
ChannelPipeline并不是直接管理ChannelHandler,而是通过ChannelHandlerContext来间接管理,这一点通过ChannelPipeline的默认实现DefaultChannelPipeline可以看出来。
调用ChannelHandlerContext#channel()方法可以得到和Context绑定的Channel,调用ChannelHandlerContext#handler()方法可以得到和Context绑定的Handler。
> 一个ChannelHandlerContext只能对应一个ChannelHander,只对应一个Channel,而一个ChannelHander则可以对应多个ChannelHandlerContext
- 在看的书和文章
- Java程序员手册
- 思维方式
- 面向服务
- Dubbo
- StringBoot
- 001.应用部署
- 002.注解学习
- SpringCloud
- SpringCloud入门
- Dbs
- 分布式
- Ffp
- 多线程
- 多线程小知识
- Java锁认识
- Netty
- Netty学习目录
- 读写事件流程分析与相关API
- 数据
- 大数据学习
- 学习目录
- Hadoop学习
- Hadoop组建安装
- ssh配置免密登陆
- Hadoop伪集群模式
- HBase伪集群模式
- Hive安装
- 常用操作命令
- 问题记录
- DOLIST
- 学习资料
- Spark
- 一些概念介绍
- 数据库
- Oracle相关
- 批量测试数据生成
- MySQL相关
- Redis
- 常用操作
- 机器学习
- 认识
- Kafka
- 监控
- 分布式相关
- RPC
- 中间件
- ElasticSearch
- ES环境搭建
- Python客户端创建索引
- Es的api常用操作
- SQL查询引擎
- Es数DB的数据同步
- ActiveMQ
- ActiveMQ介绍
- 分享
- Skyeye
- 组件安装配置
- Dubbo服务Demo应用部署
- Kafka安装配置
- RabbitMq配置
- Docker
- Docker学习文章
- Docker的大数据平台之路
- Docker环境搭建
- ubuntu16安装docker
- Docker镜像加速
- 使用Docker快速搭建中间件
- Docker环境使用mysql
- Docker环境的中间件搭建汇总
- Docker镜像容器管理
- Docker镜像创建
- Docker创建可用的系统容器
- Kubernetes
- etcd安装
- flanneld安装
- kubernetes环境安装
- kubernetes源码编译
- Linux相关
- Linux操作系统
- Deepin操作系统
- 新系统环境准备
- Linux系统小工具
- Linxu配置时间服务器同步
- DNS服务器dnsmasq
- Linux命令
- 常用命令
- 计算机基础
- README
- 数据结构
- 面试题总结
- 计算机组层原理
- 计算机组层原理
- 其它语言
- Python
- Python环境搭建
- Python学习总结
- Python语法学习
- Python模块学习
- MySQLdb
- scrapy
- Python的exception
- PythonNLP入门
- Go
- 工具组件
- Jenkins
- Jenkins认识
- Jenkins安装配置
- Jenkins插件使用
- Jenkins项目常用配置
- Git
- Git使用说明
- NLP
- 入门级别
- 一些概念
- faiss介绍
- WMD介绍