天天看點

一個輕量級分布式RPC架構--NettyRpc

1、背景

本人在這個簡易版的rpc上添加了如下特性:

* 服務異步調用的支援,回調函數callback的支援

* 用戶端使用長連接配接(在多次調用共享連接配接)

* 服務端異步多線程處理rpc請求

2、簡介

rpc,即 remote procedure call(遠端過程調用),調用遠端計算機上的服務,就像調用本地服務一樣。rpc可以很好的解耦系統,如webservice就是一種基于http協定的rpc。

這個rpc整體架構如下:

一個輕量級分布式RPC架構--NettyRpc

這個rpc架構使用的一些技術所解決的問題:

服務釋出與訂閱:服務端使用zookeeper注冊服務位址,用戶端從zookeeper擷取可用的服務位址。

通信:使用netty作為通信架構。

spring:使用spring配置服務,加載bean,掃描注解。

動态代理:用戶端使用代理模式透明化服務調用。

消息編解碼:使用protostuff序列化和反序列化消息。

3、服務端釋出服務

使用注解标注要釋出的服務

服務注解

一個服務接口:

一個服務實作:使用注解标注

一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc

服務在啟動的時候掃描得到所有的服務接口及其實作:

一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc

在zookeeper叢集上注冊服務位址:

一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc

這裡在原文的基礎上加了addrootnode()判斷服務父節點是否存在,如果不存在則添加一個persistent的服務父節點,這樣雖然啟動服務時多了點判斷,但是不需要手動指令添加服務父節點了。

4、用戶端調用服務

使用代理模式調用服務:

一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc

這裡每次使用代理遠端調用服務,從zookeeper上擷取可用的服務位址,通過rpcclient send一個request,等待該request的response傳回。這裡原文有個比較嚴重的bug,在原文給出的簡單的test中是很難測出來的,原文使用了obj的wait和notifyall來等待response傳回,會出現“假死等待”的情況:一個request發送出去後,在obj.wait()調用之前可能response就傳回了,這時候在channelread0裡已經拿到了response并且obj.notifyall()已經在obj.wait()之前調用了,這時候send後再obj.wait()就出現了假死等待,用戶端就一直等待在這裡。使用countdownlatch可以解決這個問題。

注意:這裡每次調用的send時候才去和服務端建立連接配接,使用的是短連接配接,這種短連接配接在高并發時會有連接配接數問題,也會影響性能。

從zookeeper上擷取服務位址:

一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc

每次服務位址節點發生變化,都需要再次watchnode,擷取新的服務位址清單。

5、消息編碼

請求消息:

一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc

響應消息:

一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc

消息序列化和反序列化工具:(基于 protostuff 實作)

一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc

由于處理的是tcp消息,本人加了tcp的粘包處理handler

消息編解碼時開始4個位元組表示消息的長度,也就是消息編碼的時候,先寫消息的長度,再寫消息。

6、性能改進

netty本身就是一個高性能的網絡架構,從網絡io方面來說并沒有太大的問題。

從這個rpc架構本身來說,在原文的基礎上把server端處理請求的過程改成了多線程異步:

一個輕量級分布式RPC架構--NettyRpc
一個輕量級分布式RPC架構--NettyRpc

netty 4中的handler處理在io線程中,如果handler進行中有耗時的操作(如資料庫相關),會讓io線程等待,影響性能。

個人覺得該rpc的待改進項:

* 用戶端保持和服務進行長連接配接,不需要每次調用服務的時候進行連接配接,長連接配接的管理(通過zookeeper擷取有效的位址)。

* 用戶端請求異步處理的支援,不需要同步等待:發送一個異步請求,傳回feature,通過feature的callback機制擷取結果。

* 編碼序列化的多協定支援。

項目持續更新中。

參考:

輕量級分布式 rpc 架構:http://my.oschina.net/huangyong/blog/361751

你應該知道的rpc原理:http://www.cnblogs.com/lbser/p/4853234.html

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

http://www.cnblogs.com/luxiaoxun/p/5272384.html