導航:首頁 > 編程語言 > dubbo支持python么

dubbo支持python么

發布時間:2023-09-30 00:25:09

⑴ Dubbo——HTTP 協議 + JSON-RPC

Protocol 還有一個實現分支是 AbstractProxyProtocol,如下圖所示:

從圖中我們可以看到:gRPC、HTTP、WebService、Hessian、Thrift 等協議對應的 Protocol 實現,都是繼承自 AbstractProxyProtocol 抽象類。

目前互聯網的技術棧百花齊放,很多公司會使用 Node.js、python、Rails、Go 等語言來開發 一些 Web 端應用,同時又有很多服務會使用 java 技術棧實現,這就出現了大量的跨語言調用的需求。Dubbo 作為一個 RPC 框架,自然也希望能實現這種跨語言的調用,目前 Dubbo 中使用「HTTP 協議 + JSON-RPC」的方式來達到這一目的,其中 HTTP 協議和 JSON 都是天然跨語言的標准,在各種語言中都有成熟的類庫。

下面就重點來分析 Dubbo 對 HTTP 協議的支持。首先,會介紹 JSON-RPC 的基礎,並通過一個示例,快速入門,然後介紹 Dubbo 中 HttpProtocol 的具體實現,也就是如何將 HTTP 協議與 JSON-RPC 結合使用,實現跨語言調用的效果。

Dubbo 中支持的 HTTP 協議實際上使用的是 JSON-RPC 協議。

JSON-RPC 是基於 JSON 的跨語言遠程調用協議。Dubbo 中的 bbo-rpc-xml、bbo-rpc-webservice 等模塊支持的 XML-RPC、WebService 等協議與 JSON-RPC 一樣,都是基於文本的協議,只不過 JSON 的格式比 XML、WebService 等格式更加簡潔、緊湊。與 Dubbo 協議、Hessian 協議等二進制協議相比,JSON-RPC 更便於調試和實現,可見 JSON-RPC 協議還是一款非常優秀的遠程調用協議。

在 Java 體系中,有很多成熟的 JSON-RPC 框架,例如 jsonrpc4j、jpoxy 等,其中,jsonrpc4j 本身體積小巧,使用方便,既可以獨立使用,也可以與 Spring 無縫集合,非常適合基於 Spring 的項目。

下面先來看看 JSON-RPC 協議中請求的基本格式:

JSON-RPC請求中各個欄位的含義如下:

在 JSON-RPC 的服務端收到調用請求之後,會查找到相應的方法並進行調用,然後將方法的返回值整理成如下格式,返回給客戶端:

JSON-RPC響應中各個欄位的含義如下:

Dubbo 使用 jsonrpc4j 庫來實現 JSON-RPC 協議,下面使用 jsonrpc4j 編寫一個簡單的 JSON-RPC 服務端示常式序和客戶端示常式序,並通過這兩個示常式序說明 jsonrpc4j 最基本的使用方式。

首先,需要創建服務端和客戶端都需要的 domain 類以及服務介面。先來創建一個 User 類,作為最基礎的數據對象:

接下來創建一個 UserService 介面作為服務介面,其中定義了 5 個方法,分別用來創建 User、查詢 User 以及相關信息、刪除 User:

UserServiceImpl 是 UserService 介面的實現類,其中使用一個 ArrayList 集合管理 User 對象,具體實現如下:

整個用戶管理業務的核心大致如此。下面我們來看服務端如何將 UserService 與 JSON-RPC 關聯起來。

首先,創建 RpcServlet 類,它是 HttpServlet 的子類,並覆蓋了 HttpServlet 的 service() 方法。我們知道,HttpServlet 在收到 GET 和 POST 請求的時候,最終會調用其 service() 方法進行處理;HttpServlet 還會將 HTTP 請求和響應封裝成 HttpServletRequest 和 HttpServletResponse 傳入 service() 方法之中。這里的 RpcServlet 實現之中會創建一個 JsonRpcServer,並在 service() 方法中將 HTTP 請求委託給 JsonRpcServer 進行處理:

最後,創建一個 JsonRpcServer 作為服務端的入口類,在其 main() 方法中會啟動 Jetty 作為 Web 容器,具體實現如下:

這里使用到的 web.xml 配置文件如下:

完成服務端的編寫之後,下面再繼續編寫 JSON-RPC 的客戶端。在 JsonRpcClient 中會創建 JsonRpcHttpClient,並通過 JsonRpcHttpClient 請求服務端:

在 AbstractProxyProtocol 的 export() 方法中,首先會根據 URL 檢查 exporterMap 緩存,如果查詢失敗,則會調用 ProxyFactory.getProxy() 方法將 Invoker 封裝成業務介面的代理類,然後通過子類實現的 doExport() 方法啟動底層的 ProxyProtocolServer,並初始化 serverMap 集合。具體實現如下:

在 HttpProtocol 的 doExport() 方法中,與前面介紹的 DubboProtocol 的實現類似,也要啟動一個 RemotingServer。為了適配各種 HTTP 伺服器,例如,Tomcat、Jetty 等,Dubbo 在 Transporter 層抽象出了一個 HttpServer 的介面。

bbo-remoting-http 模塊的入口是 HttpBinder 介面,它被 @SPI 註解修飾,是一個擴展介面,有三個擴展實現,默認使用的是 JettyHttpBinder 實現,如下圖所示:

HttpBinder 介面中的 bind() 方法被 @Adaptive 註解修飾,會根據 URL 的 server 參數選擇相應的 HttpBinder 擴展實現,不同 HttpBinder 實現返回相應的 HttpServer 實現。HttpServer 的繼承關系如下圖所示:

這里以 JettyHttpServer 為例簡單介紹 HttpServer 的實現,在 JettyHttpServer 中會初始化 Jetty Server,其中會配置 Jetty Server 使用到的線程池以及處理請求 Handler:

可以看到 JettyHttpServer 收到的全部請求將委託給 DispatcherServlet 這個 HttpServlet 實現,而 DispatcherServlet 的 service() 方法會把請求委託給對應接埠的 HttpHandler 處理:

了解了 Dubbo 對 HttpServer 的抽象以及 JettyHttpServer 的核心之後,回到 HttpProtocol 中的 doExport() 方法繼續分析。

在 HttpProtocol.doExport() 方法中會通過 HttpBinder 創建前面介紹的 HttpServer 對象,並記錄到 serverMap 中用來接收 HTTP 請求。這里初始化 HttpServer 以及處理請求用到的 HttpHandler 是 HttpProtocol 中的內部類,在其他使用 HTTP 協議作為基礎的 RPC 協議實現中也有類似的 HttpHandler 實現類,如下圖所示:

在 HttpProtocol.InternalHandler 中的 handle() 實現中,會將請求委託給 skeletonMap 集合中記錄的 JsonRpcServer 對象進行處理:

skeletonMap 集合中的 JsonRpcServer 是與 HttpServer 對象一同在 doExport() 方法中初始化的。最後,我們來看 HttpProtocol.doExport() 方法的實現:

介紹完 HttpProtocol 暴露服務的相關實現之後,下面再來看 HttpProtocol 中引用服務相關的方法實現,即 protocolBindinRefer() 方法實現。該方法首先通過 doRefer() 方法創建業務介面的代理,這里會使用到 jsonrpc4j 庫中的 JsonProxyFactoryBean 與 Spring 進行集成,在其 afterPropertiesSet() 方法中會創建 JsonRpcHttpClient 對象:

下面來看 doRefer() 方法的具體實現:

在 AbstractProxyProtocol.protocolBindingRefer() 方法中,會通過 ProxyFactory.getInvoker() 方法將 doRefer() 方法返回的代理對象轉換成 Invoker 對象,並記錄到 Invokers 集合中,具體實現如下:

本文重點介紹了在 Dubbo 中如何通過「HTTP 協議 + JSON-RPC」的方案實現跨語言調用。首先介紹了 JSON-RPC 中請求和響應的基本格式,以及其實現庫 jsonrpc4j 的基本使用;接下來我們還詳細介紹了 Dubbo 中 AbstractProxyProtocol、HttpProtocol 等核心類,剖析了 Dubbo 中「HTTP 協議 + JSON-RPC」方案的落地實現。

⑵ 微服務跨語言調用(摘選)

微服務架構已成為目前互聯網架構的趨勢,關於微服務的討論,幾乎占據了各種技術大會的絕大多數版面。國內使用最多的服務治理框架非阿里開源的 bbo 莫屬,千米網也選擇了 bbo 作為微服務治理框架。另一方面,和大多數互聯網公司一樣,千米的開發語言是多樣的,大多數後端業務由 java 支撐,而每個業務線有各自開發語言的選擇權,便出現了 nodejs,python,go 多語言調用的問題。

跨語言調用是一個很大的話題,也是一個很有挑戰的技術活,目前業界經常被提及的解決方案有如下幾種,不妨拿出來老生常談一番:

當我們再聊跨語言調用時我們在聊什麼?縱觀上述幾個較為通用,成熟的解決方案,可以得出結論:解決跨語言調用的思路無非是兩種:

如果一個新型的團隊面臨技術選型,我認為上述的方案都可以納入參考,可考慮到遺留系統的兼容性問題

舊系統的遷移成本

這也關鍵的選型因素。我們做出的第一個嘗試,便是在 RPC 協議上下功夫。

通用協議的跨語言支持

springmvc的美好時代

springmvc

springmvc

在沒有實現真正的跨語言調用之前,想要實現「跨語言」大多數方案是使用 http 協議做一層轉換,最常見的手段莫過於藉助 springmvc 提供的 controller/restController,間接調用 bbo provider。這種方案的優勢和劣勢顯而易見

通用協議的支持

事實上,大多數服務治理框架都支持多種協議,bbo 框架除默認的 bbo 協議之外,還有當當網擴展的 rest協議和千米網擴展的 json-rpc 協議可供選擇。這兩者都是通用的跨語言協議。

rest 協議為滿足 JAX-RS 2.0 標准規范,在開發過程中引入了 @Path,@POST,@GET 等註解,習慣於編寫傳統 rpc 介面的人可能不太習慣 rest 風格的 rpc 介面。一方面這樣會影響開發體驗,另一方面,獨樹一幟的介面風格使得它與其他協議不太兼容,舊介面的共生和遷移都無法實現。如果沒有遺留系統,rest 協議無疑是跨語言方案最簡易的實現,絕大多數語言支持 rest 協議。

和 rest 協議類似,json-rpc 的實現也是文本序列化&http 協議。bbox 在 restful 介面上已經做出了嘗試,但是 rest 架構和 bbo 原有的 rpc 架構是有區別的,rest 架構需要對資源(Resources)進行定義, 需要用到 http 協議的基本操作 GET、POST、PUT、DELETE。在我們看來,restful 更合適互聯網系統之間的調用,而 rpc 更適合一個系統內的調用。使用 json-rpc 協議使得舊介面得以兼顧,開發習慣仍舊保留,同時獲得了跨語言的能力。

千米網在早期實踐中採用了 json-rpc 作為 bbo 的跨語言協議實現,並開源了基於 json-rpc 協議下的 python 客戶端 bbo-client-py 和 node 客戶端 bbo-node-client,使用 python 和 nodejs 的小夥伴可以藉助於它們直接調用 bbo-provider-java 提供的 rpc 服務。系統中大多數 java 服務之間的互相調用還是以 bbo 協議為主,考慮到新舊協議的適配,在不影響原有服務的基礎上,我們配置了雙協議。

bbo 協議主要支持 java 間的相互調用,適配老介面;json-rpc 協議主要支持異構語言的調用。

定製協議的跨語言支持

微服務框架所謂的協議(protocol)可以簡單理解為:報文格式和序列化方案。服務治理框架一般都提供了眾多的協議配置項供使用者選擇,除去上述兩種通用協議,還存在一些定製化的協議,如 bbo 框架的默認協議:bbo 協議以及 motan 框架提供的跨語言協議:motan2。

motan2協議的跨語言支持

                                                                                                            motan2

motan2

motan2 協議被設計用來滿足跨語言的需求主要體現在兩個細節中—MetaData 和 motan-go。在最初的 motan 協議中,協議報文僅由 Header+Body 組成,這樣導致 path,param,group 等存儲在 Body 中的數據需要反序列得到,這對異構語言來說是很不友好的,所以在 motan2 中修改了協議的組成;weibo 開源了 motan-go ,motan-php ,motan-openresty ,並藉助於 motan-go 充當了 agent 這一翻譯官的角色,使用 simple 序列化方案來序列化協議報文的 Body 部分(simple 序列化是一種較弱的序列化方案)。

                                                                                                        agent

agent

仔細揣摩下可以發現這么做和雙協議的配置區別並不是大,只不過這里的 agent 是隱式存在的,與主服務共生。明顯的區別在於 agent 方案中異構語言並不直接交互。

bbo協議的跨語言支持

bbo 協議設計之初只考慮到了常規的 rpc 調用場景,它並不是為跨語言而設計,但跨語言支持從來不是只有支持、不支持兩種選擇,而是要按難易程度來劃分。是的,bbo 協議的跨語言調用可能並不好做,但並非無法實現。千米網便實現了這一點,nodejs 構建的前端業務是異構語言的主戰場,最終實現了 bbo2.js,打通了 nodejs 和原生 bbo 協議。作為本文第二部分的核心內容,重點介紹下我們使用 bbo2.js 幹了什麼事。

Dubbo協議報文格式

                                                                                                        bbo協議

bbo協議

bbo協議報文消息頭詳解:

magic:類似java位元組碼文件里的魔數,用來判斷是不是 bbo 協議的數據包。魔數是常量 0xdabb

flag:標志位, 一共8個地址位。低四位用來表示消息體數據用的序列化工具的類型(默認 hessian),高四位中,第一位為 1 表示是 request 請求,第二位為 1 表示雙向傳輸(即有返回 response),第三位為 1 表示是心跳 ping 事件。

status:狀態位, 設置請求響應狀態,bbo 定義了一些響應的類型。具體類型見com.alibaba.bbo.remoting.exchange.Response

invoke id:消息 id, long 類型。每一個請求的唯一識別 id(由於採用非同步通訊的方式,用來把請求 request 和返回的 response 對應上)

body length:消息體 body 長度, int 類型,即記錄 Body Content 有多少個位元組

body content:請求參數,響應參數的抽象序列化之後存儲於此。

協議報文最終都會變成位元組,使用 tcp 傳輸,任何語言只要支持網路模塊,有類似 Socket 之類的封裝,那麼通信就不成問題。那,跨語言難在哪兒?以其他語言調用 java 來說,主要有兩個難點:

ps:bbo 協議通訊demo( https://github.com/lexburner/Dubbojs-Learning )

閱讀全文

與dubbo支持python么相關的資料

熱點內容
程序員投行 瀏覽:313
java多線程讀取文件 瀏覽:145
香港外貿伺服器有什麼好處 瀏覽:612
鄧倫參加密室大逃脫結果變成團寵 瀏覽:847
購買文件伺服器怎麼選擇 瀏覽:720
空調壓縮機高壓報警 瀏覽:498
u盤數控程序放哪個文件夾 瀏覽:853
python模擬微信登錄其他APP 瀏覽:301
綁扎鋼筋加密區規范 瀏覽:671
怎麼更換手機壁紙安卓 瀏覽:808
閑魚app賣手機怎麼走驗機 瀏覽:821
安卓三個按鍵音怎麼關閉 瀏覽:64
esp8266手機app源碼 瀏覽:713
伺服器如何建立多個站點 瀏覽:151
加密狗可以在筆記本上做賬嗎 瀏覽:888
學生雲伺服器推薦 瀏覽:509
android銀行卡快捷支付 瀏覽:828
海口手機直播系統源碼 瀏覽:416
怎麼給加密貨幣加圖標 瀏覽:999
phpheader編碼 瀏覽:766