在Dubbo的'人生'中, 無論它是在自己的'親爸爸'阿里家族成長, 還是'寄養(yǎng)'在Apache家族里, Dubbo的底層通信一直使用高性能的Netty框架.
Dubbo在阿里家族一直成長到v2.6.9版本之后,就被送到Apache家族了.
通過Maven官網(wǎng)搜索Dubbo版本, 如下
從上面兩張圖看出, Dubbo在阿里家族的Maven最高版本是v2.6.9, 在Apache家族的Maven最低版本是v2.7.0, 正好銜接.
在之前的Netty在Dubbo中使用了哪些Handler文章中, 介紹了在服務端或客戶端啟動之后, 流程的處理過程涉及哪些Handler. 下面提供一張更全面的圖
上面這張圖, 涉及了Dubbo使用Netty作為客戶端和服務端時啟動的主要核心代碼, 包括核心類, 以及心跳等內(nèi)容. 接下來逐一說下每個部分內(nèi)容.
圖中代碼的對應Dubbo版本是v2.6.9
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.9</version>
</dependency>
圖中內(nèi)容分成三個區(qū)域, 左邊和右邊分別對應啟動服務端和啟動客戶端時對應 的Netty代碼, 包括使用的Handler. 中間部分涉及客戶端和服務端的
HeaderExchangeServer和HeaderExchangeClient, 還有心跳相關.
在服務端啟動過程中, 會創(chuàng)建一個HeaderExchangeServer類,
它有一個NettyServer屬性, 還有一個ScheduledExecutorService屬性.
NettyServer就是負責監(jiān)聽客戶端連接以及讀寫IO操作(具體是由Netty相關的類實現(xiàn)的). 當有數(shù)據(jù)到達服務端的時候, 從圖上來看, 就會從上到下經(jīng)過每個Handler, 當需要向客戶端寫數(shù)據(jù)的時候, 就會從下到上經(jīng)過每個Handler.
ScheduledExecutorService類是一個定時任務相關的線程池. 當客戶端沒有向服務端發(fā)送請求的時候, 也就意味著沒有數(shù)據(jù)到達服務端了. 通過這個定時任務可以定時向客戶端發(fā)送心跳包, 正常情況, 客戶端收到服務端的心跳包之后, 會響應一個心跳包給服務端, 服務端接收到客戶端的響應心跳包之后, 什么業(yè)務也不會做. 不管是正常的業(yè)務數(shù)據(jù)發(fā)送和接收, 還是心跳包的發(fā)送和接收, 接收到包就會更新最后讀的時間, 發(fā)送包就會更新最后寫的時間. 根據(jù)最后讀或者寫的時間來判斷, 經(jīng)過了這么久還是沒有收到對端的響應包, 那么服務端最后就會斷開與客戶端的連接. 簡單說明就是, 服務端會根據(jù)最后一次讀/寫的時間判斷, 比如已經(jīng)過了1分鐘了, 客戶端還是沒有給服務端發(fā)送數(shù)據(jù), 那么服務端就會給客戶端發(fā)送心跳包, 發(fā)了幾次心跳包之后(至于發(fā)送幾次是根據(jù)時間大小判斷的)還是沒有收到客戶端的心跳包, 那么服務端就會斷開連接.
在客戶端啟動過程中, 會創(chuàng)建一個HeaderExchangeClient類, 它有一個NettyClient屬性, 還有一個ScheduledExecutorService屬性.NettyClient是負責讀寫IO操作(具體是由Netty相關的類實現(xiàn)的). 當有數(shù)據(jù)到達客戶端的時候, 從圖上來看, 就會從上到下經(jīng)過每個Handler, 當需要向服務端寫數(shù)據(jù)的時候, 就會從下到上經(jīng)過每個Handler.
在創(chuàng)建NettyClient的時候,會創(chuàng)建一個ScheduledThreadPoolExecutor. 這個線程池負責重連服務端, 它也是定時的檢查連接是否關閉, 如果關閉了那么就會重連服務端.
在v2.6.9版本, 即阿里家族的版本, 實現(xiàn)心跳檢測是通過客戶端和服務端互發(fā)心跳包的方式實現(xiàn)的, 更具體的說是通過JDK的線程池實現(xiàn)定時檢測的.
ScheduledThreadPoolExecutor scheduled = new ScheduledThreadPoolExecutor();
而就在v2.7.0版本, 也就是Dubbo捐獻給Apache的第一個版本, 心跳檢測的實現(xiàn)使用的是時間輪(HashedWheelTimer)的方式. 只是實現(xiàn)的方式不同而已, 但是服務端依然會發(fā)送心跳包.
可是到了v2.7.3版本, 不僅僅增加了使用Netty的IdleStateHandler類進行空閑檢測, 雖然還使用了時間輪, 但是服務端已經(jīng)不再發(fā)送心跳包了, 服務端一旦發(fā)現(xiàn)連接空閑, 直接斷開連接了.
雜談結(jié)束...