RPC框架基本原理(一):服務注冊


什么是RPC框架

RPC整個過程涉及四類對象:客戶端、客戶端代理、服務端和服務端代理。RPC要求客戶端和服務端之間約定好調用接口和傳輸格式(如JSON,Xml等),客戶端在調用該接口時,由客戶端的代理對象負責對調用的參數(包括調用的函數名和參數等信息)進行格式轉換,使之符合約定的傳輸格式,並通過網絡傳送至服務端。數據傳輸至服務端后,交由服務端代理對象進行格式解碼,獲取調用的接口和參數,最后調用服務端對象相應的方法獲取結果並返回客戶端。服務端的服務地址發布到ConfigServer,並推送給客戶端,各種配置和規則信息通過Diamond發布訂閱,服務的基本信息采集到Redis中。

基本的調用關系圖如下

這張圖是解釋RPC注冊中心經典的圖,圖中的ConfigServer可以看做是一個內存數據庫,它主要有兩個功能:

  1. 服務提供者的地址和服務信息
  2. 向服務訂閱者推送所訂閱的服務提供者的地址信息

這里需要注意的是:真正發起遠程調用是在消費者端和服務端生產者端和ConfigServer沒有直接關系,實際的RPC是一個點對點的過程,通過TCP進行通信。

架構圖如下:

服務注冊的流程

  • 服務與spring容器綁定,監聽容器的fresh,close等事件,進行服務的注冊與關閉,
  • 第一個服務注冊時,首先校驗該服務是否已經注冊,如果hsf依賴的netty服務未啟動,啟動netty服務,這里涉及nio的輪詢線程池(hsfwork),以及后端具體hsf處理線程池(bizProcess),這些線程池是同步的,可以采用listenerFuture進行異步解構。
  • 啟動好服務后,注冊服務的基本信息到configserver中(注冊流程分為注冊前,注冊,注冊后)。

關鍵的技術

Netty服務

常見I/O模型

  • 阻塞I/O(blocking I/O)
  • 非阻塞I/O (nonblocking I/O)
  • I/O復用(select,poll,epoll) (I/O multiplexing)
  • 信號驅動I/O (signal driven I/O (SIGIO))
  • 異步I/O (asynchronous I/O (the POSIX aio_functions))

阻塞I/O(blocking I/O)

非阻塞I/O (nonblocking I/O)


用戶進程其實是需要不斷的主動詢問kernel數據好了沒有。因為需要不斷地輪詢,這消耗了大量的CPU的資源。

I/O復用(select,poll,epoll)

select:

select本質上是通過設置或者檢查存放fd標志位的數據結構來進行下一步處理。這樣所帶來的缺點是:

  • 單個進程可監視的fd數量被限制,即能監聽端口的大小有限。
  • 一般來說這個數目和系統內存關系很大,具體數目可以cat /proc/sys/fs/file-max察看。32位機默認是1024個。64位機默認是2048.

對socket進行掃描時是線性掃描,即采用輪詢的方法,效率較低:
當套接字比較多的時候,每次select()都要通過遍歷FD_SETSIZE個Socket來完成調度,不管哪個Socket是活躍的,都遍歷一遍。這會浪費很多CPU時間。如果能給套接字注冊某個回調函數,當他們活躍時,自動完成相關操作,那就避免了輪詢,這正是epoll與kqueue做的。

需要維護一個用來存放大量fd的數據結構,這樣會使得用戶空間和內核空間在傳遞該結構時復制開銷大

poll:

poll本質上和select沒有區別,它將用戶傳入的數組拷貝到內核空間,然后查詢每個fd對應的設備狀態,如果設備就緒則在設備等待隊列中加入一項並繼續遍歷,如果遍歷完所有fd后沒有發現就緒設備,則掛起當前進程,直到設備就緒或者主動超時,被喚醒后它又要再次遍歷fd。這個過程經歷了多次無謂的遍歷。

它沒有最大連接數的限制,原因是它是基於鏈表來存儲的,但是同樣有一個缺點:

大量的fd的數組被整體復制於用戶態和內核地址空間之間,而不管這樣的復制是不是有意義。 2. poll還有一個特點是“水平觸發”,如果報告了fd后,沒有被處理,那么下次poll時會再次報告該fd。

epoll:

epoll支持水平觸發和邊緣觸發,最大的特點在於邊緣觸發,它只告訴進程哪些fd剛剛變為就需態,並且只會通知一次。還有一個特點是,epoll使用“事件”的就緒通知方式,通過epoll_ctl注冊fd,一旦該fd就緒,內核就會采用類似callback的回調機制來激活該fd,epoll_wait便可以收到通知。

Java從1.4開始提供了NIO工具包,支持用 I/O復用模型來進行網絡編程。其模式圖:

信號驅動I/O (signal driven I/O (SIGIO))

異步I/O (asynchronous I/O (the POSIX aio_functions))


這種模型與信號驅動模型的主要區別是:信號驅動I/O由內核通知我們何時可以開始一個I/O操作,而異步I/O模型由內核通知我們I/O操作何時已經完成.

JDK1.7 升級了NIO 類庫,升級后的NIO類庫被稱為NIO2.0。java也正是提供了異步文件I/O操作,同時提供了與UNIX網絡編程事件驅動I/O對應的AIO。

Netty4的beta3加了AIO了,但是到beta9又被去了,作者的意思是測試下來AIO性能不如NIO,所以沒必要用,在Linux上NIO的實現本身就是epoll,使用jdk的AIO沒有意義,在windows上jdk的AIO實現是IOCP,這種情況下使用AIO是比poll的性能高的,但是netty的服務器一般是在linux上,所以拋棄windows沒啥大不了,windows最多做個客戶端,用nio也就夠了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM