中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

攜程的 Dubbo 之路

發布時間:2020-08-08 08:47:14 來源:ITPUB博客 閱讀:110 作者:大濤學長 欄目:關系型數據庫
本篇文章整理自董藝荃在 Dubbo 社區開發者日上海站的演講。

緣起

攜程當初為什么要引入 Dubbo 呢?實際上從 2013 年底起,攜程內主要使用的就是基于 HTTP 協議的 SOA 微服務框架。這個框架是攜程內部自行研發的,整體架構在這近6年中沒有進行大的重構。受到當初設計的限制,框架本身的擴展性不是很好,使得用戶要想自己擴展一些功能就會比較困難。另外,由于 HTTP 協議一個連接同時只能處理一個請求。在高并發的情況下,服務端的連接數和線程池等資源都會比較緊張,影響到請求處理的性能。而 Dubbo 作為一個高性能的 RPC 框架,不僅是一款業界知名的開源產品,它整體優秀的架構設計和數據傳輸方式也可以解決上面提到的這些問題。正好在 2017 年下半年,阿里宣布重啟維護 Dubbo 。基于這些原因,我們團隊決定把 Dubbo 引入攜程。

Dubbo 落地第一步

要在公司落地 Dubbo 這個新服務框架,第一步就是解決服務治理和監控這兩個問題。

服務治理

在服務治理這方面,攜程現有的 SOA 框架已經有了一套完整的服務注冊中心和服務治理系統。對于服務注冊中心,大家比較常用的可能是 Apache Zookeeper 。而我們使用的是參考 Netflix 開源的 Eureka 自行研發的注冊中心 Artemis 。Artemis 的架構是一個去中心的對等集群。各個節點的地位相同,沒有主從之分。服務實例與集群中的任意一個節點保持長連接,發送注冊和心跳信息。收到信息的節點會將這些信息分發給其他節點,確保集群間數據的一致性。客戶端也會通過一個長連接來接受注冊中心推送的服務實例列表信息。


在服務數據模型方面,我們直接復用了現有 SOA 服務的數據模型。如圖所示,最核心的服務模型對應的是 Dubbo 中的一個 interface 。一個應用程序內可以包含多個服務,一個服務也可以部署在多個服務器上。我們將每個服務器上運行的服務應用稱為服務實例。


所有的服務在上線前都需要在治理系統中進行注冊。注冊后,系統會為其分配一個唯一的標識,也就是 ServiceID 。這個 ServiceID 將會在服務實例注冊時發送至注冊中心用來標識實例的歸屬,客戶端也需要通過這個ID來獲取指定服務的實例列表。


由于 Dubbo 本身并沒有 ServiceID 的設計,這里的問題就是如何向注冊中心傳遞一個 interface 所對應的 ServiceID 信息。我們的方法是在 Service 和 Reference 配置中增加一個 serviceId 參數。ArtemisServiceRegistry 的實現會讀取這個參數,并傳遞給注冊中心。這樣就可以正常的與注冊中心進行交互了。


服務監控

在服務監控這方面我們主要做了兩部分工作:統計數據層面的監控和調用鏈層面的監控。
統計數據指的是對各種服務調用數據的定期匯總,比如調用量、響應時間、請求體和響應體的大小以及請求出現異常的情況等等。這部分數據我們分別在客戶端和服務端以分鐘粒度進行了匯總,然后輸出到 Dashboard 看板上。同時我們也對這些數據增加了一些標簽,例如:Service ID、服務端 IP 、調用的方法等等。用戶可以很方便的查詢自己需要的監控數據。


在監控服務調用鏈上,我們使用的是 CAT 。CAT 是美團點評開源的一個實時的應用監控平臺。它通過樹形的 Transaction 和 Event 節點,可以將整個請求的處理過程記錄下來。我們在 Dubbo 的客戶端和服務端都增加了 CAT 的 Transaction 和 Event 埋點,記錄了調用的服務、 SDK 的版本、服務耗時、調用方的標識等信息,并且通過 Dubbo 的 Attachment 把 CAT 服務調用的上下文信息傳遞到了服務端,使得客戶端和服務端的監控數據可以連接起來。在排障的時候就可以很方便的進行查詢。在圖上,外面一層我們看到的是客戶端記錄的監控數據。在調用發起處展開后,我們就可以看到對應的在服務端的監控數據。

初版發布

在解決了服務治理和監控對接這兩個問題后,我們就算完成了 Dubbo 在攜程初步的一個本地化,在 2018 年 3 月,我們發布了 Dubbo 攜程定制版的首個可用版本。在正式發布前我們需要給這個產品起個新名字。既然是攜程(Ctrip)加 Dubbo ,我們就把這個定制版本稱為 CDubbo 。

CDubbo 功能擴展

除了基本的系統對接,我們還對 CDubbo 進行了一系列的功能擴展,主要包括以下這 5 點: Callback 增強、序列化擴展、熔斷和請求測試工具。下面我來逐一給大家介紹一下。

Callback 增強

首先,我們看一下這段代碼。請問代碼里有沒有什么問題呢?


這段代碼里有一個 DemoService 。其中的 callbackDemo 方法的參數是一個接口。下面的 Demo 類中分別在 foo 和 bar 兩個方法中調用了這個 callbackDemo 方法。相信用過 Callback 的朋友們應該知道,foo 這個方法的調用方式是正確的,而 bar 這個方法在重復調用的時候是會報錯的。因為對于同一個 Callback 接口,客戶端只能創建一個實例。
但這又有什么問題呢?我們來看一下這樣一個場景。


一個用戶在頁面上發起了一個查詢機票的請求。站點服務器接收到請求之后調用了后端的查詢機票服務。考慮到這個調用可能會耗時較長,接口上使用了 callback 來回傳實際的查詢結果。然后再由站點服務器通過類似 WebSocket 的技術推送給客戶端。那么問題來了。站點服務器接受到回調數據時需要知道它對應的是哪個用戶的哪次調用請求,這樣才能把數據正確的推送給用戶。但對于全局唯一的callback接口實例,想要拿到這個請求上下文信息就比較困難了。需要在接口定義和實現上預先做好準備。可能需要額外引入一些全局的對象來保存這部分上下文信息。
針對這個問題,我們在 CDubbo 中增加了 Stream 功能。跟前面一樣,我們先來看代碼。


這段代碼與前面的代碼有什么區別?首先, callback 接口的參數替換為了一個 StreamContext 。還有接受回調的地方不是之前的全局唯一實例,而是一個匿名類,并且也不再是單單一個方法,而是有3個方法,onNext、onError和onCompleted 。這樣調用方在匿名類里就可以通過閉包來獲取原本請求的上下文信息了。是不是體驗就好一些了?
那么 Stream 具體是怎么實現的呢?我們來看一下這張圖。


在客戶端,客戶端發起帶 Stream 的調用時,需要通過 StreamContext.create 方法創建一個StreamContext。雖然說是創建,但實際是在一個全局的 StreamContext 一個唯一的 StreamID 和對應回調的實際處理邏輯。在發送請求時,這個 StreamID 會被發送到服務端。服務端在發起回調的時候也會帶上這個 StreamID 。這樣客戶端就可以知道這次回調對應的是哪個 StreamContext 了。

序列化擴展

攜程的一些業務部門,在之前開發 SOA 服務的時候,使用的是 Google Protocol Buffer 的契約編寫的請求數據模型。 Google PB 的要求就是通過契約生成的數據模型必須使用PB的序列化器進行序列化。為了便于他們將 SOA 服務遷移到Dubbo ,我們也在 Dubbo 中增加了 GooglePB 序列化方式的支持。后續為了便于用戶自行擴展,我們在PB序列化器的實現上增加了擴展接口,允許用戶在外圍繼續增加數據壓縮的功能。整體序列化器的實現并不是很難,倒是有一點需要注意的是,由于 Dubbo 服務對外只能暴露一種序列化方式,這種序列化方式應該兼容所有的 Java 數據類型。而 PB 碰巧就是那種只能序列化自己契約生成的數據類型的序列化器。所以在遇到不支持的數據類型的時候,我們還是會 fallback 到使用默認的 hessian 來進行序列化操作的。

請求熔斷

相信大家對熔斷應該不陌生吧。當客戶端或服務端出現大范圍的請求出錯或超時的時候,系統會自動執行 fail-fast 邏輯,不再繼續發送和接受請求,而是直接返回錯誤信息。這里我們使用的是業界比較成熟的解決方案:Netflix 開源的 Hystrix 。它不僅包含熔斷的功能,還支持并發量控制、不同的調用間隔離等功能。單個調用的出錯不會對其他的調用造成影響。各項功能都支持按需進行自定義配置。CDubbo的服務端和客戶端通過集成 Hystrix 來做請求的異常情況進行處理,避免發生雪崩效應。

服務測試工具

Dubbo 作為一個使用二進制數據流進行傳輸的 RPC 協議,服務的測試就是一個比較難操作的問題。要想讓測試人員在無需編寫代碼的前提下測試一個 Dubbo 服務,我們要解決的有這樣三個問題:如何編寫測試請求、如何發送測試請求和如何查看響應數據。
首先就是怎么構造請求。這個問題實際分為兩個部分。一個是用戶在不寫代碼的前提下用什么格式去構造這個請求。考慮到很多測試人員對 Restful Service 的測試比較熟悉,所以我們最終決定使用 JSON 格式表示請求數據。那么讓一個測試人員從一個空白的 JSON 開始構造一個請求是不是有點困難呢?所以我們還是希望能夠讓用戶了解到請求的數據模型。雖然我們使用的是 Dubbo 2.5.10 ,但這部分功能在 Dubbo 2.7.3 中已經有了。所以我們將這部分代碼復制了過來,然后對它進行了擴展,把服務的元數據信息保存在一個全局上下文中。并且我們在 CDubbo 中通過 Filter 增加了一個內部的操作,$serviceMeta,把服務的元數據信息暴露出來。這部分元數據信息包括方法列表、各個方法的參數列表和參數的數據模型等等。這樣用戶通過調用內部操作拿到這個數據模型之后,可以生成出一個基本的JSON結構。之后用戶只需要在這個結構中填充實際的測試數據就可以很容易的構造出一個測試請求來。


然后,怎么把編輯好的請求發送給服務端呢?因為沒有模型代碼,無法直接發起調用。而 Dubbo 提供了一個很好的工具,就是泛化調用, GenericService 。我們把請求體通過泛化調用發送給服務端,再把服務端返回的Map序列化成JSON顯示給測試人員。整個測試流程就完成了。順便還解決了如何查看響應數據的問題。


為了方便用戶使用,我們開發了一個服務測試平臺。用戶可以在上面直接選擇服務和實例,編寫和發送測試請求。另外為了方便用戶進行自動化測試,我們也把這部分功能封裝成了 jar 包發布了出去。


其實在做測試工具的過程中,還遇到了一點小問題。通過從 JSON 轉化 Map 再轉化為 POJO 這條路是能走通的。但前面提到了,有一些對象是通過類似 Google Protobuf 的契約生成的。它們不是單純的 POJO ,無法直接轉換。所以,我們對泛化調用進行了擴展。首先對于這種自定義的序列化器,我們允許用戶自行定義從數據對象到 JSON 的格式轉換實現。其次,在服務端處理泛化調用時,我們給 Dubbo 增加了進行 JSON 和 Google PB 對象之間的互相轉換的功能。現在這兩個擴展功能有已經合并入了 Dubbo 的代碼庫,并隨著 2.7.3 版本發布了。

堡壘測試網關

說完了單純針對服務的測試,有些時候我們還希望在生產的實際使用環境下對服務進行測試,尤其是在應用發布的時候。在攜程,有一個叫堡壘測試的測試方法,指的是在應用發布過程中,發布系統會先挑出一臺服務器作為堡壘機,并將新版本的應用發布到堡壘機上。然后用戶通過特定的測試方法將請求發送到堡壘機上來驗證新版本應用的功能是否可以正常工作。由于進行堡壘測試時,堡壘機尚未拉入集群,這里就需要讓客戶端可以識別出一個堡壘測試請求并把請求轉發給指定的堡壘服務實例。雖然我們可以通過路由來實現這一點,但這就需要客戶端了解很多轉發的細節信息,而且整合入 SDK 的功能對于后續的升級維護會造成一定的麻煩。所以我們開發了一個專門用于堡壘測試的服務網關。當一個客戶端識別到當前請求的上下文中包含堡壘請求標識時,它就會把 Dubbo 請求轉發給預先配置好的測試網關。網關會先解析這個服務請求,判斷它對應的是哪個服務然后再找出這個服務的堡壘機并將請求轉發過去。在服務完成請求處理后,網關也會把響應數據轉發回調用方。


與一般的 HTTP 網關不同, Dubbo 的服務網關需要考慮一個額外的請求方式,就是前面所提到的 callback 。由于 callback 是從服務端發起的請求,整個處理流程都與客戶端的正常請求不同。網關上會將客戶端發起的連接和網關與服務端之間的連接進行綁定,并記錄最近待返回的請求 ID 。這樣在接收到 callback 的請求和響應時就可以準確的路由了。

后續功能規劃

截止到今天, CDubbo 一共發布了27個版本。攜程的很多業務部門都已經接入了 Dubbo 。在未來, CDubbo 還會擴展更多的功能,比如請求限流和認證授權等等。我們希望以后可以貢獻更多的新功能出來,回饋開源社區。
本文作者:董藝荃
原文鏈接
本文為云棲社區原創內容,未經允許不得轉載。
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

莫力| 宁乡县| 绥德县| 天水市| 靖远县| 湘乡市| 乾安县| 成都市| 宁河县| 涡阳县| 平南县| 北碚区| 新津县| 通海县| 乐山市| 奉节县| 揭阳市| 淄博市| 广丰县| 丰镇市| 鄂伦春自治旗| 兰西县| 长子县| 赤城县| 绥江县| 鹤峰县| 土默特左旗| 澜沧| 武平县| 苗栗县| 柘城县| 大港区| 台州市| 道孚县| 霍城县| 漳平市| 德阳市| 洛隆县| 宽甸| 克什克腾旗| 资兴市|