當前位置:
首頁 > 科技 > 阿里巴巴 Dubbo Nacos 服務發現開發最佳實踐

阿里巴巴 Dubbo Nacos 服務發現開發最佳實踐

作者 | 坤宇

Nacos 是阿里巴巴在服務發現與配置管理領域開源的新產品,由在其內部生產上久經考驗的相關產品如 Diamond,VIPServer 等演化而來。而其中的服務發現功能,在內部支撐著百萬級的連接和億級的 QPS 服務調用。開源的 Nacos 雖然為了能夠符合開源質量的標準,在內部基礎上做了一些代碼的重構和精鍊,但是整體架構和內部是一致的。阿里巴巴為什麼選用目前 Nacos 所使用的架構,這不是本篇文章要討論的,本文意在幫助大家找到一個使用 Nacos 服務發現的最佳姿勢,用法優劣並無絕對,也希望 Nacos 社區積極將怎麼使用 Nacos 服務發現功能開放交流及貢獻代碼,大家一起參與 Nacos 產品的開源演進,為國內自主的服務發現產品添磚加瓦。

服務 - 集群 - 實例

Nacos 服務發現提供與其他服務發現產品不太一樣的機制以及概念,在這裡稍作介紹,下文中的內容都會多次提到這裡介紹的概念,因此掌握這些概念,對於用好 Nacos 服務發現至關重要。

不同於 Consul, Eureka, Nacos 的服務發現使用的領域數據模型是服務 - 集群 - 實例這樣的三層結構。最上面是服務,註冊端(服務發布者)和訂閱端(服務消費者)使用服務來與其他服務做區分,服務發現中,服務是必須指定的。集群則是中間一層,一個服務又會劃分為多個集群,每個集群都有它的自定義配置,Nacos 提供了一個默認集群和相應的默認配置,在不需要多集群的場景下,可以不用指定集群。最下一層是實例,每個集群又會包含多個實例,這樣對服務進行發現時,可以發現多個集群的所有實例,也可以指定集群,來發現特定集群的實例。

環境準備

首先,需要有一個 Nacos Server 部署起來,目前 Nacos 支持單機模式,也支持集群模式,部署文檔可以參考 Nacos 快速入門。然後添加 Nacos 客戶端最新版本依賴:

你可以配置從中央倉庫直接依賴,也可以將 Nacos 最新源碼下載下來,本地構建客戶端版本。

Hello World

我們先來進行一個最簡單的服務註冊與發現。Nacos 支持從客戶端註冊服務實例和訂閱服務,具體步驟如下:

配置 Nacos 客戶端 Properties:

創建 Nacos Naming 客戶端:

註冊一個實例:

查找這個服務的實例:

至此一個最簡單的 Nacos 服務發現的使用已經完成了。這裡要對一些細節稍作解釋。首先在第一步中,屬性 PropertyKeyConst.SERVER_ADDR 表示的是 Nacos 服務端的地址,這個地址的格式為 IP:port,IP:port。對於單機版,只需要指定一個 IP:port。甚至您可以將埠省略,這樣將會訪問 Nacos 的默認埠 8848。在第二步中,將創建一個 NamingService 實例,客戶端將為該實例創建單獨的資源空間,包括緩存、線程池以及配置等。Nacos 客戶端沒有對該實例做單例的限制,請小心維護這個實例,以防新建了多於預期的實例。第三步註冊服務中,使用的是最簡單的 API 註冊方式,只需要傳入服務名、IP、埠就可以。第四步是獲取服務下的所有實例列表,包括健康和不健康的。

構建自定義實例

在一些場景中,我們希望註冊的實例中,有一些能夠被分配更多的流量,而另外一些分配較少的流量,或者能夠傳入一些實例的元信息存儲到 Nacos 服務端,例如 IP 所屬的應用或者所在的機房,這樣在客戶端可以根據服務下掛載的實例的元信息,來自定義負載均衡模式。別擔心,我們有另外的註冊實例介面,讓你可以在註冊的時候指定實例的屬性:

這個方法可以在註冊服務的時候,傳入一個 Instanc 實例,而在 Instance 實例中,可以設置實例的若干屬性:

其中,InstanceId 是由服務端生成返回給客戶端,用於唯一標識該實例。IP、埠是實例的基本屬性,除此之外,還有 weight 權重,可以設置該實例所分配流量的多少,這應該也比較好理解,權重越大,實例分配的流量就會越大。healthy 欄位代表該實例是否健康,這個值也是由服務端返回給客戶端的。cluster 和 service 分別表示該實例對應的集群和服務的一些信息,這些信息會在下面做介紹。最後是實例的元數據,這個元數據一個 String 對 String 的 Map。那麼可以用如下代碼來註冊一個自定義實例:

構建自定義集群

Nacos 引入了集群的概念,在服務這個維度下面,可以對服務下的實例列表再做個劃分。這在阿里巴巴內部非常普遍。一個典型的場景是這個服務下的實例,需要配置多種健康檢查方式,有一些實例使用 TCP 的健康檢查方式,另外一些使用 HTTP 的健康檢查方式。另一個場景是,這個服務下掛載的機器分屬不同的環境,我們希望能夠在某些情況下(包括演練)將某個環境的流量全部切走,這樣可以通過配置一個環境屬於一個集群,來做到一次性切流。

在客戶端構建自定義集群,有一些陷阱需要小心。當前我們只有註冊實例的介面,實例內部的 cluster 欄位可以配置集群的屬性。但是多個實例之間如果配置了不同的集群屬性,這時候會發生什麼呢?Nacos 只會接受第一次註冊該集群所傳入的集群屬性,也就是說,先註冊的實例,獲得優先權,將它對應的集群信息註冊到 Nacos 服務端。只有 Nacos 服務端已經存在該集群的配置,後續的註冊請求里的集群信息,都會被忽略。為了確保你的應用保持預期的行為,請務必讓同一個集群下的實例使用相同的集群配置。

下面來看看可以為集群定義哪些配置:

首先是集群對應的服務名,用來表示該集群所屬的服務;然後是集群的名字、健康檢查方式、默認的埠、默認的健康檢查埠以及是否使用是的埠做健康檢查。我們先來說簡單的,默認埠表示註冊時實例默認的埠,這個在客戶端並沒有體現,但是當使用 API 註冊實例的時候,埠是可以不傳入的,此時就會用這個默認埠作為實例的埠。然後是默認的健康檢查埠,當健康檢查方式中沒有配置埠時,就會用這個埠來和實例通信,進行健康檢查。下一個屬性是是否使用實例埠做健康檢查,如果設為 true,則會使用實例註冊的埠來和實例進行通信。最後一個屬性是集群的元數據,Nacos 支持多個維度的元數據,實例支持,集群支持,下面介紹的服務屬性也支持。

健康檢查方式,客戶端心跳是一種模式,由客戶端主動上報健康狀態。服務端檢測是另外一種模式,Nacos 目前支持三種:TCP、HTTP 和 MYSQL。TCP 方式會從 Nacos 服務端建立一個連接到實例,如果連接建立成功,則表示該實例健康。HTTP 方式則會從 Nacos 服務端想實例發起一個 HTTP 請求,可以配置的屬性有訪問的相對路徑,訪問的 HTTP 頭部,這個頭部使用豎線進行分割,以及預期的請求返回碼,默認為 200:

MYSQL 健康檢查方式,則可以讓 Nacos 往實例執行一條 MySQL 命令,可以配置的屬性有用戶名、密碼和執行的命令。執行結果如果不拋異常,則表示實例健康:

構建自定義服務

同理,服務也可能需要自定義的配置,Nacos 的服務隨著實例的註冊而存在,並隨著所有實例的註銷而消亡。目前除了使用 HTTP API 可以修改服務的屬性外(這將在未來的篇章中進行介紹),就只能使用註冊實例時傳入服務屬性來進行服務的自定義配置。這裡的服務與 Consul 或者 Eureka 不同,Consul 與 Eureka 的服務其實就是指的實例,而每個實例有一個服務名,通過這個服務名來獲取相同服務名下的實例列表,服務本身並不是一個數據實體。在真正的生產環境中,我們認為服務本身也是具有數據存儲需求的,例如作用於服務下所有實例的配置、許可權控制等。雖然有一些配置可以放到實例級別,例如健康檢查是否開啟。但是當服務的規模成千上萬後,想要整體修改這些實例的健康檢查開關,就是一個繁重的運維操作。另一些配置,例如下文會提到的健康保護閾值,是一定是一個服務只有一個唯一的值的,多個值將會造成邏輯上的衝突。

服務的屬性存儲在 Service 類中,自上而下,依次是服務的名稱、服務的健康保護閾值、服務的應用名、服務的分組、服務的健康檢查模式以及服務的元數據。相關概念這裡不再做一一陳述,你可以參考 Nacos 官網 概念介紹。這裡要提到的是服務的健康保護閾值,在阿里巴巴內部,這個值被廣泛的設置和調優。在這裡對該屬性的初衷做一個簡單的介紹。分散式服務場景下的一個問題是在部分實例不健康的情況下,是否能夠將流所有流量引向其他健康實例?在一些情況下,這可能造成雪崩效應。即本來健康的實例被多餘的流量衝擊,也變得不健康,然後導致健康的實例越來越少,最後整個服務崩潰。此時可以使用這個健康保護閾值,當健康實例與所有實例的比例小於這個值的時候,則認為所有實例都是健康的,這樣雖然部分流量流向了不健康的實例,但是剩餘健康的實例還是能夠正常訪問的。

服務發現

Nacos 的服務發現,有主動拉取和推送兩種模式,這與一般的服務發現架構相同。在拉取方式中,提供了三個方法,一個是查詢所有註冊的實例,一個是只查詢健康且上線的實例,還有一個是獲取一個健康且上線的實例。一般情況下,訂閱端並不關心不健康的實例或者權重設為 0 的實例,但是也不排除一些場景下,有一些運維或者管理的場景需要拿到所有的實例。目前的版本同時還支持根據服務端設定的負載均衡策略,來查詢單個可用的實例。就好像 DNS 解析一樣,雖然每次都返回一個後端 IP,但是整體可以保證域名掛載的所有 IP 會按照一定的策略都能夠被客戶端解析到。

前兩個查詢方法會返回所有實例的列表,這允許用戶通過額外的工作,將實例的權重或者元數據運用到負載均衡中。對於一般的微服務場景,針對每個實例輪詢,這樣已經足夠了。事實上,不管是在 Eureka 還是 Consul 里,其原生客戶端都是只負責服務的發現,並不支持負載均衡。這樣就需要第三方的 ribbon 或者 fabio 來完成負載均衡工作,此時它們的負載均衡,是完全放在客戶端的。

Nacos 也會支持客戶端側的負載均衡,並支持用戶擴展的負載均衡策略。不過在阿里巴巴內部,通常只需要由服務端來配置負載均衡策略,所有的調用端不區分業務的使用同一套負載均衡策略。因為實際上,調用端往往並不關心自身訪問的服務的流量分配,而只需要一個可用的服務節點就可以了。而服務提供端,則由於其部署規模很大和部署環境的複雜,需要對環境信息敏感的流量分配以及對流量的絕對控制權。這時,往往需要提供端審慎的配置好統一的負載均衡策略,來保證所有訂閱端按照這個策略來進行訪問。

除了主動查詢實例列表,Nacos 還提供訂閱模式來感知服務下實例列表的變化,包括服務配置或者實例配置的變化。可以使用下面的介面來進行訂閱或者取消訂閱:

控制台使用

Nacos 0.3.0 版本上線了控制台,作為生產環境基本的運維工具,服務發現也通過控制台釋放了部分的運維能力。雖然控制台承擔的是運維為主的工作,但是開發人員也需要通過控制台來查看當前服務的註冊狀態和健康狀態等,服務發現的控制台頁面介紹可以參考 https://nacos.io/en-us/blog/discovery-console.html。雖然這篇文章中的一些頁面通過社區的反饋而做了細微的調整,但是通過這篇文章應該可以掌握怎麼使用服務發現的控制台了。控制台的啟動方式也很簡單,將 Nacos 安裝包下載安裝啟動(安裝教程)之後,直接訪問:http://localhost:8848/nacos/index.html 即可打開最新的控制台界面。

小 結

Nacos 目前的版本,集成了服務發現和配置管理的基本能力以及部分高級特性。作為最小生產可用版本,Nacos 未來還會繼續開放新特性,結合 SpringCloud、K8S、Dubbo 等生態,為開發者提供極致易用和穩定的服務管理和配置管理能力。在可預期的幾個版本內,將會支持元數據的管理及 DNS 的服務發現。爭取將使用 Nacos,作為服務發現和配置管理選型的最佳實踐。

坤宇即將在本屆 ArchSummit 全球架構師峰會為大家帶來新的分享—阿里 10 年大規模微服務「軟負載」技術體系原理及實踐,他希望通過這個分享,和大家交流阿里巴巴這 10 年來在軟負載體系的實踐之路,並且共同看看該領域的未來趨勢。

由 InfoQ 中國主辦的 ArchSummit 全球架構師峰會即將於 12 月 7-8 日在北京國際會議中心舉辦,大會日程已新鮮出爐,聽 100+ 知名企業的架構師分享架構實踐,與一線技術大牛將現場深入交流,機會難得,千萬不要錯過了!


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 InfoQ 的精彩文章:

Serverless如何高可用?這不是問題
微眾銀行:互聯網下半場的一個轉型樣本丨今晚直播

TAG:InfoQ |