[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介紹