咱們公司是杭州的一家電商公司,公司內的技術體系較多,主要語言有了JAVA/PHP/Node,其中在19年的時候,公司制定了去PHP化的計劃,將後端邏輯沉澱到Java服務化當中,而部分服務化調用相關業務則須要Node扛起,而與Java進行通訊則須要通過Dubbo,由此咱們以Consumer的角色來探索與研究如何用Node調用Dubbo.javascript
Dubbo是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向接口的遠程方法調用,智能容錯和負載均衡,以及服務自動註冊和發現。java
官方雖然支持了不少種協議,可是真正適合於咱們的協議並非不少,譬如rmi協議主要是面向Java工程之間的調用,並不適合用於異構語言RPC場景,因此咱們接下來只針對部分協議進行分析,並結合咱們的實際的業務場景,最後來篩選出適合咱們的協議.git
鏈接個數 | 鏈接方式 | 傳輸協議 | 傳輸方式 | 序列化 | 適用範圍 | 適用場景 | |
---|---|---|---|---|---|---|---|
dubbo | 單鏈接 | 長鏈接 | TCP | NIO 異步傳輸 | Hessian 二進制序列化 | 傳入傳出參數數據包較小,消費者比提供者個數多,單一消費者沒法壓滿提供者 | 常規遠程服務方法調用 |
rmi | 多鏈接 | 短鏈接 | TCP | 同步傳輸 | Java 標準二進制序列化 | 傳入傳出參數數據包大小混合,消費者與提供者個數差很少,可傳文件。 | 常規遠程服務方法調用,與原生RMI服務互操做 |
hessian | 多鏈接 | 短鏈接 | HTTP | 同步傳輸 | Hessian二進制序列化 | 傳入傳出參數數據包較大,提供者比消費者個數多,提供者壓力較大,可傳文件。 頁面傳輸,文件傳輸,或與原生hessian服務互操做 | |
http | 多鏈接 | 短鏈接 | HTTP | 同步傳輸 | 表單序列化 | 傳入傳出參數數據包大小混合,提供者比消費者個數多,可用瀏覽器查看,可用表單或URL傳入參數 需同時給應用程序和瀏覽器 JS 使用的服務。 | |
rest | 多鏈接 | 短鏈接 | HTTP | 同步傳輸 | 表單序列化 | 同http,適用於更加符合rest規範的服務 | 同http |
從使用場景上來看,dubbo協議是比較符合咱們實際業務需求的,因爲其數據包相較於Http協議體積小不少,傳輸速度也會更快,另外咱們能夠經過socket與provider創建長鏈接,能夠減小反覆建連帶來的沒必要要的網絡開銷.使用此協議,咱們須要注意的幾個點是github
小結 : 若是想要採用此協議鏈接Provider,可使用dubbo官方推薦dubbo2.js後端
此協議是基於http,因此對consumer端就基本上沒有了限制.並且此協議咱們在拼接好參數以後,能夠直接經過瀏覽器或者是HTTP請求工具便可查看結果,使用友好程度上來說,會優於dubbo. consumer端能夠直接使用request庫請求,也不存在協議解析以及socket狀態維護的問題,消費端的代碼實現難度也會比較小.使用此協議,咱們須要注意的幾個點 :瀏覽器
小結 : 性能上雖不及dubbo.但對開發人員相對友好,能夠結合業務自身場景進行選擇.網絡
dubbo是支持一個服務以多種協議註冊,好比一個服務能夠同時註冊dubbo://
和rest://
,若是你想用http,可是目前公司所暴露出來的協議只支持dubbo,能夠和提供服務的同窗商量一下,額外再添加一個http協議成本也是能在接收範圍內的.負載均衡
目前引用服務有兩個方案,分別是框架
直接引用服務,顧名思義就是繞開註冊中心獲取咱們所想要的服務提供者,因爲繞開了註冊中心,天然也沒法作到服務發現,並且因爲單點問題,沒法作到負載均衡以及高可用,因此生產環境不推薦使用此模式的
.異步
可是因爲其開發上的便利性,在開發環境/測試環境仍能夠嘗試使用此模式.
由上圖所示,開發同窗聯調過程當中,須要在項目工程中對指定服務開發同窗的機器進行直連,而其餘沒有指定的服務將會默認走註冊中心.爲了不對工程代碼的侵入性,咱們會在工程中創建應對不一樣環境的dubbo.properies,而dubbo.properies不會加入到工程的版本控制當中,主要用於解決不一樣環境下的服務直連問題.其中服務的控制粒度能夠精確到具體的服務.
經過註冊中心發現引用服務,Dubbo經常使用的引用服務方式,能夠作到服務自動發現,負載均衡.正式環境調用基本基於此模式.其中註冊中心實現有不少種,例如Zookeeper/Redis/Multicast.官方推薦Zookeeper.
服務請求體結構,是在對dubbo在註冊中心上註冊信息的抽象以後的一層封裝,一方面能夠提高開發人員的開發效率,另外下降開發人員自身手動拼接請求的錯誤率.
咱們基於dubbo/rest兩種協議,來分析一下這兩種協議在註冊中心註冊包含哪些信息.
dubbo://192.168.1.2:10880/com.service.ProductService?dubbo=2.8&methods=getById,getByName
rest://192.168.1.2:10081/service/com.service.ProductService?dubbo=2.8&methods=getById,getByName
咱們對這兩個協議公共部分進行提取一下
dubbo://
.com.service.ProductService
基於上述服務結構構成的分析,dubbo和rest服務請求結構構成大致相似,咱們對不一樣的協議請求的能夠作以下定義.
// 1. dubbo協議的請求體定義
services.ProductService = (dubbo) => dubbo.proxyService({
dubboInterface: 'com.service.ProductService',
methods: {
getById(id) {
return [java.Long(id)];
},
getByName(name) {
return [java.String(name)];
}
},
});
複製代碼
// rest 請求體定義
services.ProductService = (dubbo) => dubbo.proxyService({
dubboInterface: 'com.service.ProductService',
methods: {
getById(id) {
return {
method: 'get',
query: [parseInt(id)]
};
},
getByName(name) {
return [String(name)];
}
},
});
複製代碼
二者最大不一樣點在於參數定義上的不一樣,dubbo須要強制轉換爲強類型,而rest不須要.
咱們在對服務定義完成以後,接下來就會面臨一個使用上的問題,最直接的方法就是爲每一個工程每一個服務新建一個服務文件,可是一用就會發現一個問題請求定義的文件分散在不一樣工程,沒法進行統一維護升級,維護成本較高.
咱們第一個反應是每一個服務抽象出來,各自成爲一個獨立的NPM包,譬如MemberService咱們能夠抽象成爲@dubbo-service/member-service
,這樣就能夠解決文件分散在不一樣工程致使的維護問題.
事情到這裏,咱們已經解決了服務如何統必定義的問題,可是仍然沒有解決統一管理與維護的問題.如 :
若是你以爲此篇文章對你有幫助,就順手點個贊吧~ 很是感謝
有什麼疑問能夠直接評論回覆或者私信我,我會盡我所能回覆你~