1. 程式人生 > >使用PHP和Node.js連線dubbo服務

使用PHP和Node.js連線dubbo服務

使用PHP和Node.js連線dubbo服務

 

DUBBO是一個分散式服務框架,致力於提供高效能和透明化的RPC遠端服務呼叫方案,是阿里巴巴SOA服務化治理方案的核心框架,每天為2,000+個服務提供3,000,000,000+次訪問量支援,並被廣泛應用於阿里巴巴集團的各成員站點。

不巧的是我司也在用,之前的解決方案是JAVA包裝成HTTP的restful API給中間層Node.js或者PHP呼叫,但是其實有時候需求比較緊急的情況下,直接RPC遠端呼叫可能能解決一些燃眉之急。

由於技術棧是PHP和Node.js,前一陣子研究了一下,總結一下,希望能幫助到有類似場景的同學,也分享一下遇到這種根本不瞭解的問題是如何去解決的過程,PS,我之前沒有JAVA開發背景和PHP開發背景。

一,瞭解dubbo和他的RPC遠端呼叫原理。

首先是這張圖分了幾個角色,是從官網拿來的:

Provider: 暴露服務的服務提供方。
Consumer: 呼叫遠端服務的服務消費方。
Registry: 服務註冊與發現的註冊中心。
Monitor: 統計服務的呼叫次調和呼叫時間的監控中心。
Container: 服務執行容器。

說的通俗一點,我們要拿PHP或者NodeJs實現一個Consumer,而Consumer與Monitor和Registry是有關聯的,與Provider是有呼叫關係的。

這個圖和上面這段話理解後,簡單分析下,dubbo服務的Registry一般使用的都是zookeeper作為註冊中心,Monitor需要在消費方和服務提供方進行監控統計,這裡只需要實現Monitor消費方的通知即可。

二,實現方案。

上面只是簡單的分析出來需求,那麼如何實現這個Consumer呢,通過檢視幾個已經存在的開源專案,比如node.js比較有名的,很多人都在用的,支援hessian協議的 p412726700/node-zookeeper-dubbo,還有支援jsonrpc呼叫的hufeng/node-jsonrpc-dubbo,他們的實現基本上思路是一樣的,包括幾個PHP的專案:quickj/dubbo-php-client

既然大家都已經實現了,我講講我看到的原始碼和一些關鍵程式碼吧。

三,Node.js連線原理

1,基本所有的庫都是使用alexguan/node-zookeeper-client

來連線的Registry,使用zookeeper.createClient方法來建立zookeeper例項。

2,從zookeeper連線後的例項中拿到對應服務提供者提供的的dubbo協議集合,使用getChildren方法。

3,對拿到的集合遍歷,記得要decodeURIComponent,然後對URL做解析,比如是http開頭的dubbo協議,還是dubbo開頭的協議,需要分別儲存。

4,協議中是包含了RPC呼叫的所有dubbo方法的,此時需要把對應的方法進行儲存,有的框架對方法做了屬性拷貝,屬性對應的方法內容就是一個invoke呼叫,有的則是對invoke做了API,你自己去傳入RPC呼叫的方法名。

5,對不同協議編寫不同的呼叫實現方法,如HTTP的呼叫使用node-json-rpc,而dubbo協議則使用hessian的庫。

6,分析dubbo協議原理,簡單概括就是基於hessian協議,傳輸前需要序列化,傳輸成功後使用hessian的反序列化方法拿到結果,傳輸使用socket方法連線。

7,序列化使用https://github.com/node-modules/hessian.js 自帶js-to-java功能,但是這裡需要注意,拿到成功返回結果後,如果decode失敗,一定要檢查java服務方法返回的最好是List,Map,Array這種常規JAVA資料型別,否則可能反序列化失敗解析不出js物件。

8,完成呼叫,快取例項,對Monitor做通知,詳細格式參見dubbo Monitor原始碼:https://github.com/alibaba/dubbo/blob/master/dubbo-monitor/dubbo-monitor-api/src/main/java/com/alibaba/dubbo/monitor/MonitorService.java#L68

 

四,PHP連線原理

因為我是先了解了NodeJs的大概一個呼叫和實現過程的,那麼再看PHP的,其實就不難了。我這裡做一個最小化的解釋,我PHP並不太好……屬於現學現賣。

1,先找能連zookeeper的類,ZooKeeper - Manual

2,同樣使用getChild方法解析出dubbo的協議集合,並且urldecode,再分析儲存住對應可以invoke的方法名,協議呼叫地址。

3,php中的invoke方法實現為先socket_create方法建立一個連線,connect之後socket_write傳送請求,然後讀回結果,再json_decode(包含中文結果記得轉編碼)。

4,write引數格式為:invoke com.xx.xx.interfaces.service.method("args")

5,傳送Monitor通知。

 

總結:

其實總結一下,理論上Node.js也是可以轉寫成PHP的實現方式,PHP也可以轉寫成Node.js的實現方式,語言雖然不一樣,原理和呼叫方式都是相同,如果之後有時間,業務中經常使用這種場景,還是要自己親自實現一個的好。

做前端真難。。所以我如果上面有說錯的地方,大家指正,後續我再修改,希望幫助到想了解的朋友。