<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
上一小章我們介紹了解碼器, 這一章我們介紹編碼器
其實編碼器和解碼器比較類似, 編碼器也是一個handler, 並且屬於outbounfHandle, 就是將準備發出去的資料進行攔截, 攔截之後進行相應的處理之後再次進傳送處理, 如果理解了解碼器, 那麼編碼器的相關內容理解起來也比較容易
我們之前在學習pipeline的時候, 講解了write事件的傳播過程, 但在實際使用的時候, 我們通常不會呼叫channel的write方法, 因為該方法只會寫入到傳送資料的快取中, 並不會直接寫入channel中, 如果想寫入到channel中, 還需要呼叫flush方法
實際使用過程中, 我們用的更多的是writeAndFlush方法, 這方法既能將資料寫到傳送快取中, 也能重新整理到channel中
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ctx.channel().writeAndFlush("test data"); }
學過netty的同學們對此肯定不陌生, 通過這種方式, 可以將資料傳送到channel中, 對方可以收到響應
首先會走到AbstractChannel的writeAndFlush:
public ChannelFuture writeAndFlush(Object msg) { return pipeline.writeAndFlush(msg); }
繼續跟到DefualtChannelPipeline中的writeAndFlush方法中:
public final ChannelFuture writeAndFlush(Object msg) { return tail.writeAndFlush(msg); }
這裡我們看到, writeAndFlush是從tail節點進行傳播, 有關事件傳播, 我們再pipeline中進行過剖析, 相信這個不會陌生
繼續跟, 會跟到AbstractChannelHandlerContext中的writeAndFlush方法:
public ChannelFuture writeAndFlush(Object msg) { return writeAndFlush(msg, newPromise()); }
繼續跟:
public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) { if (msg == null) { throw new NullPointerException("msg"); } if (!validatePromise(promise, true)) { ReferenceCountUtil.release(msg); // cancelled return promise; } write(msg, true, promise); return promise; }
繼續跟write方法:
private void write(Object msg, boolean flush, ChannelPromise promise) { //findContextOutbound()尋找前一個outbound節點 //最後到head節點結束 AbstractChannelHandlerContext next = findContextOutbound(); final Object m = pipeline.touch(msg, next); EventExecutor executor = next.executor(); if (executor.inEventLoop()) { if (flush) { next.invokeWriteAndFlush(m, promise); } else { //沒有調flush next.invokeWrite(m, promise); } } else { AbstractWriteTask task; if (flush) { task = WriteAndFlushTask.newInstance(next, m, promise); } else { task = WriteTask.newInstance(next, m, promise); } safeExecute(executor, task, promise, m); } }
這裡的邏輯我們也不陌生, 找到下一個節點, 因為writeAndFlush是從tail節點開始的, 並且是outBound的事件, 所以這裡會找到tail節點的上一個outBoundHandler, 有可能是編碼器, 也有可能是我們業務處理的handler
if (executor.inEventLoop()) 判斷是否是eventLoop執行緒, 如果不是, 則封裝成task通過nioEventLoop非同步執行, 我們這裡先按照是eventLoop執行緒分析
首先, 這裡通過flush判斷是否呼叫了flush, 這裡顯然是true, 因為我們呼叫的方法是writeAndFlush
private void invokeWriteAndFlush(Object msg, ChannelPromise promise) { if (invokeHandler()) { //寫入 invokeWrite0(msg, promise); //重新整理 invokeFlush0(); } else { writeAndFlush(msg, promise); } }
這裡就真相大白了, 其實在writeAndFlush中, 首先呼叫write, write完成之後再呼叫flush方法進行的重新整理
首先跟到invokeWrite0方法中:
private void invokeWrite0(Object msg, ChannelPromise promise) { try { //呼叫當前handler的wirte()方法 ((ChannelOutboundHandler) handler()).write(this, msg, promise); } catch (Throwable t) { notifyOutboundHandlerException(t, promise); } }
該方法我們在pipeline中已經進行過分析, 就是呼叫當前handler的write方法, 如果當前handler中write方法是繼續往下傳播, 在會繼續傳播寫事件, 直到傳播到head節點, 最後會走到HeadContext的write方法中
跟到HeadContext的write方法中:
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { unsafe.write(msg, promise); }
這裡通過當前channel的unsafe物件對將當前訊息寫到快取中, 寫入的過程, 我們之後的小節進行分析
回到到invokeWriteAndFlush方法中:
private void invokeWriteAndFlush(Object msg, ChannelPromise promise) { if (invokeHandler()) { //寫入 invokeWrite0(msg, promise); //重新整理 invokeFlush0(); } else { writeAndFlush(msg, promise); } }
private void invokeFlush0() { try { ((ChannelOutboundHandler) handler()).flush(this); } catch (Throwable t) { notifyHandlerException(t); } }
同樣, 這裡會呼叫當前handler的flush方法, 如果當前handler的flush方法是繼續傳播flush事件, 則flush事件會繼續往下傳播, 直到最後會呼叫head節點的flush方法, 如果我們熟悉pipeline的話, 對這裡的邏輯不會陌生
跟到HeadContext的flush方法中:
public void flush(ChannelHandlerContext ctx) throws Exception { unsafe.flush(); }
這裡同樣, 會通過當前channel的unsafe物件通過呼叫flush方法將快取的資料重新整理到channel中, 有關重新整理的邏輯, 我們會在以後的小節進行剖析
以上就是writeAndFlush的相關邏輯, 整體上比較簡單, 熟悉pipeline的同學應該很容易理解
更多關於Netty分散式編碼器及寫資料事件的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45