虎牙在全球 DNS 秒級生效上的實踐

本文整理自虎牙中間件團隊在 Nacos Meetup 的現場分享,阿里巴巴中間件授權發佈。數據庫

  1. 阿里巴巴中間件公衆號對話框發送「虎牙」,獲取這次分享的完整 PPT(PDF版)下載連接 & 直播回顧連接。
  2. 對文中的技術細節如有疑問,歡迎留言,做者將逐一回復。

此次分享的是全球 DNS 秒級生效在虎牙的實踐,以及由此產生的一些思考,總體上,分爲如下5各部分:編程

  • 背景介紹;
  • 方案設計和對比;
  • 高可用;
  • 具體實踐和落地;
  • 規劃;

背景介紹

虎牙用到的基礎技術不少,DNS 是其中比較重要的一個環節。後端

 

 

DNS 的解析過程很關鍵,例如上圖中的 DNS 解析器經過一個定位解析追蹤到咱們的 DNS,再到本地域名服務器迭代解析,通過根域再到.com名,最後到http://huya.com的根域名,獲取最終的解析結果。緩存

在這個過程當中, DNS解析是自然的分佈式架構,每一層都會有緩存,上一層出現問題掛掉,下一層都會有緩存進行容災。另外,整個 DNS 協議支持面廣,包括手機和 PC,咱們用的編程框架裏也有 DNS 解析器,服務器也會配 DNS 解析引擎,所以,DNS 在虎牙的基礎設施中是很重要的部分。服務器

虎牙的 DNS 的應用現狀

虎牙當前主要是依賴於公共的 DNS,相信在座的小夥伴們或多或少都會遇到過下面這些問題:網絡

  • 依賴公共 localDNS,解析不穩定,延遲大。
  • 記錄變動生效時間長,沒法及時屏蔽線路和節點異常對業務的影響。例如,權威 DNS 全球各節點數據同步時間不可控,全局生效時間超過10分鐘;localDNS 緩存過時時間不可控,部分 localDNS 不遵循TTL時間,緩存時間超過48小時。
  • 內部 DNS 功能缺失,沒法解決內部服務調用面臨挑戰。例如,時延大、解析不許、支持多種調度策略。
  • 沒法知足國外業務的快速發展,雖然一些海外雲廠商提供了基於 DNS 的快速擴容方案,以及基於 DNS 的數據庫切換方案。

方案設計和對比

基於以上的問題,咱們開始從新規劃 DNS 的設計。架構

名字服務架構

 

 

整個規劃會分三個方面,核心是咱們作了「名字服務」的中心點,基於此,能夠知足咱們的需求。負載均衡

一方面經過 Nacos Sync,將現有多個註冊中心的服務, 同步到「名字服務」中, 經過 DNS 實現不一樣框架之間的 Rest 服務方式的調用, 實現例如 Eureka,Consul,Taf等框架之間的服務調用。框架

另外一方面,在全球負載均衡的場景下,因爲虎牙是以音視頻業務爲主,而音視頻業務對節點的延遲是很是敏感的,因此咱們但願一旦出現節點延遲的狀況,能立馬作切換。異步

第三個是傳統 DNS 的場景, 能夠知足容器和物理機的 DNS 需求, 提供本機 Agent 和集羣兩種方案, 經過緩存和 prefect 大大提升 DNS 解析的可用性和加快生效時間。

 

 

對於名字服務的整體設計主要分3部分,接入層須要提供 API,消息通知和 DNS 接入的能力。核心功能須要能在基於現有網絡數據,CMDB 和 IP 庫的數據基礎上,提供靈活的負載均衡能力,全球數據的秒級同步,多個數據源的同步,能對全網服務的健康狀態進行監控,及時感知到大範圍的節點異常,而且可以及時將節點的屏蔽的信息推送到端上。

最終,咱們選擇 Nacos 做爲名字服務的核心,提供統一的 API ,包括名字註冊、變化推送、負載均衡等;Nacos Sync 做爲全球集羣間數據同步的組件;DNS - F是客戶端組件,用於攔截 DNS 請求,實現基於 DNS 的名字服務。

改造先後 DNS 變動生效流程的不一樣

接下來,咱們經過對比看下改造先後 DNS 變動生效流程的差別。

 

 

原有 DNS 變動生效流程中,對 DNS 生效時間有影響的是:

Auth DNS:

跨區域、跨國數據同步慢,不穩定。

bind 在數據量比較大的時候,同步比較慢。

Local DNS:

根據 TTL 緩存,過時後纔會刷新數據。

部分廠商不遵循 TTL 時間緩存,超過24小時的緩存時間。

服務器:

服務器開啓 nscd 作 DNS 緩存。

業務進程:

應用的 DNS 緩存,好比 Java 虛擬機、框架層的 DNS 緩存。

以上四種狀況會比較影響 DNS 的變動生效流程,下圖是咱們現有的 DNS 變動生效流程:

 

 

總體上相對簡單,只要業務進程這邊將本身內部的 DNS 緩存關掉, 經過 DNS-F 進行查詢的時候, 會直接到最近的 Nacos 集羣拉取最新的服務節點信息, 並且後續節點的變化也會推送到 DNS-F 中, 後續能夠直接在緩存中獲取最新信息。

國內 Nacos 集羣:

集羣內經過 raft 協議同步數據,毫秒級別完成同步。

Nacos Sync:

Nacos 推送變化到 Nacos Sync,跨區域、跨國網絡差的狀況下可能會致使推送結果丟失,或者延遲加大。

Nacos Sync 會主動拉取實例變動,拉取週期和監聽的服務數量會影響到變動時效。

DNS - F:

Nacos 會將變動推送到 DNS - F,網絡差的狀況可能會致使推送結果丟失,或者延遲加大。

DNS - F 會主動拉取實例變動,拉取週期和監聽的服務數量會影響到變動時效。

業務進程:

經過應用禁用 DNS 緩存來解決。

核心設計 Nacos

Nacos 有兩套推送機制。

 

 

一種是經過客戶端來選擇一個可獲節點,好比它第一次拉取的是一個正常節點,這個正常節點就會跟它維護一個訂閱關係,後面有變化就會有一個相應的實地變化推送給我。若是當前節點掛掉, 他會經過重連, 在節點列表上,連上一個正常的節點。這時候會有新的 DNS 關係出現。

另外一種是經過 SDK 的方式,在服務端尋找可獲節點。服務端每一個節點之間, 會進行一個可活的探測, 選擇其中一個可活節點用戶維護這個訂閱關係。 當這個節點出現問題, 鏈接斷開後, SDK 從新發送訂閱請求,服務端會再次選擇另一個可活的節點來維護這個訂閱關係。這就保證整了推送過程不會由於某個節點掛掉而沒有推送。

推送的效率方面,主要是用 UDP 的方式,這個效率不像 TCP 消耗那麼高。

以上兩個方案都比較適合咱們目前的場景。

核心組件設計 Nacos Sync

咱們選擇 Nacos Sync 做爲多集羣數據同步的組件,主要是從如下4方面進行考慮的。

  • 同步粒度:

Nacos Sync 同步數據的時候是以服務爲維度, 比較容易作最終一致性處理, 同時能夠提供保活的機制,知足節點維持的場景。 數據庫經過 Binlog 同步的方式只能侷限於事務粒度, 而文件同步只能經過單個文件的粒度, 在服務同步這個維度並非很合適。

  • 可用性方面:

Nacos Sync 做爲一箇中間件,是以集羣方式進行的,傳統的數據庫和文件方式基本是單進程進行的,可用性方面可能不太知足要求。

  • 同步方式方面:

Nacos Sync 經過在服務粒度的全量寫入,知足服務註冊和 DNS 這兩種場景, 不須要額外的事務消耗, 能保證最終一致便可。

  • 環形同步:

咱們國內有多個可獲的節點,但願它們之間的數據能夠進行環形同步,每一個節點之間是相互備份的,這時候用 Nacos Sync 的話,是支持的。雖然數據庫方面,比較經典的是主主同步,但若是同時對一個主件進行更新的話,每個點進行協助是會有問題的,並且文件方面是不支持的。

Nacos Sync 和開源版本的不一樣

咱們對 Nacos Sync 開源方案上作了幾處修改,以更好的適用於如今的場景:

第一,經過配置方式對任務進行分拆。由於在實際應用場景裏面,由於 Nacos Sync 的任務達一兩萬,單機很容易到達瓶頸,因此咱們經過配置的方式將這些分片到多臺 Nacos Sync 機器上。

第二,經過事件合併和隊列控制的方式控制 Nacos 集羣的寫入量,以保證後端的穩定性。雖然下發事件一秒鐘只有一個,但在不少場景中,例如須要 K8s 或者 Taf 進行數據同步的時候,變化的頻率是很是高的,這時候經過事件合併,每一個服務單獨進行一個寫入進程。這樣經過隊列控制的方式能夠控制整個 Nacos 集羣的寫入量。

第三,添加了能支持從K8s 和 Taf 同步數據的功能。後期咱們會將這個特性提交給 Nacos,讓更多的開發者使用。

核心組件設計 DNS - F

DNS - F是基於 CoreDNS 上開發的,咱們擴展瞭如下 4 個組件:

Nacos 插件:查詢 Nacos 服務信息,監聽 Nacos 服務變化,並將服務轉化爲域名,實現以 DNS 協議爲基礎的服務發現;

Cache 插件:提供域名緩存服務;

Log 插件:將 DNS 解析日誌上報到日誌服務;

Proxy 插件:代理解析外部域名;

DNS - F 和開源版本的不一樣

第一,在日誌組件裏面將日誌上傳到本身的日誌服務。

第二,對緩存功能作了一個加強。通常的緩存功能可能根據 TTL 時間會過時,咱們把這個過時時間給去掉了,直接令到緩存永遠不會過時,而後經過異步將這個緩存進行刷新。好比 TTL 可能快到到時間了,咱們就會主動作一個查詢或者推送查詢,這樣,服務端或者公共 DNS 出現問題的時候,就不會影響到總體服務。

第三,加強了高可用的保障能力。包括進程監控、內部運營和外部運營的探測。另外,原來的開源版本用的是本機部署的方式,咱們作成了集羣化的部署,解決了服務推送、服務負載均衡方面的問題。

高可用

接下來由咱們團隊的李志鵬,分享一下虎牙在高可用方面的實踐。

周健同窗跟你們介紹了項目的背景跟方案設計,我來和你們介紹一下具體的實踐和落地,實踐過程當中的主要關注點是高可用。

全球化部署方案

 

 

這是虎牙的一個全球化的部署方案,咱們在全球部署了兩個大區,分別是國內和國外。這兩個大區是指定服務同步的,走的是專線,這樣能夠保障同步的穩定性。在一個大區內咱們又部署了多個接入點,例如在國內大區,咱們部署了深圳和無錫兩個接入點,這兩個節點的數據是互相同步、互爲備份,保證在一個集羣掛掉下能夠切換到另一個集羣。

多個接入點的狀況下,咱們經過 HttpDNS 實現客戶端的就近接入。客戶端按期請求 HttpDNS,HttpDNS 能根據地域尋找就近接入點。若是接入點出現故障,咱們就直接在HttpDNS 把這個節點給摘除,這樣客戶端就能快速地切換到另一個接入點。

接下來說一下單個集羣下的部署方案。

 

 

單個集羣部署了多個 Nacos 節點,並經過7層負載均衡的方式暴露給外面使用,而且提供了多個 VIP,知足不一樣線路和區域的接入要求。同時,Nacos Sync 作了分片處理,將同步壓力分散到各個分片上,一個分片下咱們又部署了多個 Nacos Sync 的節點,以保障多活和高可用。

線上演練

演練的場景是模擬一個單個集羣掛了和兩個集羣都掛了。

 

 

從圖中能夠看到,把深圳的流量切走以後,無錫的流量就漲上去了,而後再把無錫的流量切走,再關閉服務,這樣就能夠看到兩邊的流量已經沒了。以後,再去恢復兩個集羣的流量,看一下整個切換過程當中對服務的影響。

 

 

首先看一下對寫入的影響,在單個集羣掛了的狀況下,是沒有任何影響的。若是是兩個集羣都掛了,寫入就會失敗。能夠看到,這個圖有一個波峯,這個波峯就是咱們兩個集羣都掛了的狀況下,寫入失敗延遲加大。

可是切換的整個過程對 DNS-F 是沒有任何影響的,延遲保持平穩。此外,在集羣從新上線前,咱們須要作數據校驗,保證集羣之間元數據和實例數據的最終一致。

可用性級別方面,咱們能夠保障:

  • 單集羣掛掉後不會有影響;
  • 雙集羣掛掉後只會影響域名變動,不影響域名解析;

線上演練數據校驗機制

運行過程當中,咱們也要保證集羣間數據的一致性。咱們經過全量校驗和增量校驗兩種手段去保證,全量校驗方式以下:

  • 大區內部作10分鐘的全量校驗,保證大區內各個集羣數據的一致;
  • 大區之間作2分鐘作一次全量校驗,保證大區之間被同步的服務的數據一致性。

增量校驗方式以下:

  • 從其餘數據源同步的數據,經過數據源的時間戳,作增量校驗;
  • 基於API的寫入日誌,按期校驗寫入的內容是否已經所有同步。

DNF - S 高可用

關於 DNS - F 的高可用,咱們主要作了如下5個點:

  • Agent 的健康狀態監測,包括進程存活和是否能正常解析;
  • 緩存內部域名,並作持久化處理,保證 Nacos 集羣出現問題時不會影響內部域名的解析;
  • 提供備用節點,保證在 DNS-F 掛了,或者是 DNS-F 須要升級的狀況下,也不會影響到內部域名解析;
  • resolv.conf 配置檢查,發現127.0.0.1不在配置中會自動添加;
  • 限制 Agent 的 CPU 的使用,避免對業務進程形成影響。

具體的實踐和落地

實踐一:數據庫域名改造

以前的數據庫是用 IP 方式接入的,在數據庫切換的時候,須要通知每一個業務方修改配置,重啓服務,這樣就帶來一個問題:整個過程是不可控的,取決於業務方的響應速度,生效時間一般超過十分鐘。

 

 

提高數據庫切換的關鍵點,第一個就是切換時不須要業務方參與,能在業務方無感知的狀況下進行切換;第二個是實例變化能秒級推送到咱們的應用,將應用快速切換到一個新的實例上。

 

 

你們能夠看一下這個圖,這是咱們如今作的一個改造,圖中的 DMX 是虎牙內部的一個數據庫管理系統,思路就是把 DMX 和名字服務打通。DMX 會把數據庫實例信息以服務的形式註冊到名字服務,服務名就是域名。

實際應用過程當中,經過這個域名去訪問數據庫,應用在訪問前首先會通過 DNS - F 去作域名的解析,解析的時候是從名字服務查詢實例信息,而後把實例的IP返回給應用。這樣,應用就能經過 IP 和咱們的數據庫實例進行鏈接。

切換的時候,在 DMX 平臺修改域名對應的實例信息,並把變動推送到名字服務,名字服務再推送給 DNS-F,應用在下一次解析的時候就能拿到新的實例 IP,達到切換數據庫實例的目的。

這套方案落地後,虎牙的數據庫切換基本上在10秒鐘以內可以完成。

實踐二:內部調用使用內部域名

虎牙部份內部系統之間調用是經過7層負載均衡,可是因爲沒有內部 DNS,須要經過的公共的 LocalDNS 來解析,這就帶來一些問題:

問題一:擴縮容的時候要去修改 DNS 記錄,整個過程生效時間可能會超過10分鐘,故障的節點會影響業務較長的時間。

問題二:公共的 LocalDNS 智能解析不許確,好比無錫的機器可能會解析到深圳的一個接入點,影響接入質量。

問題三:不支持定製化的負載均衡策略,例如同機房、同大區優先的策略,經過公共 LocalDNS 是實現不了的。

若是想要提高內部服務調用質量,一是 DNS 記錄變動繞過 LocalDNS,把 DNS 的記錄變動直接推到 DNS-F。二是與內部系統打通,從 CMDB 等內部系統獲取機器信息,支持多種負載均衡策略。

 

 

你們能夠看一下上面的圖,這個改造和數據庫域名的改造思路是同樣的,最右上角有一個7層負載管理系統,咱們把這個系統和名字服務打通,7層負載管理系統會把域名信息以服務形式註冊到名字服務,變動域名記錄時直接從7層負載管理系統推送到名字服務,名字服務再推送到 DNS-F,達到快速切換的目的。

若是域名配置了負載均衡策略,名字服務會從 CMDB 獲取機器、機房等信息,打標到域名的實例信息。而後,DNS-F 查詢名字服務時,會攜帶 ClientIp,名字服務根據 ClientIp 的CMDB 信息過濾實例列表,返回同機房的實例給 DNS-F,達到同機房優先的目的。

由此帶來的效果是:

第一,服務擴縮容可以秒級完成,減小了故障時間。

第二,擴展了 DNS 的負載均衡策略,例若有些業務是須要在不一樣區域有不一樣的接入點的,並且不能跨區域調用,以前的 DNS 負載均衡策略是不能知足這個需求的,但在改造以後,咱們能根據 CMDB 信息去作同區域調度的負載均衡策略。

第三,業務在接入內部域名以後,延遲會有明顯的降低。上圖顯示的就是某個服務在接入到內部域名以後,延遲出現明顯的降低。

另外一個落地的效果就是咱們對主機上的域名解析的優化。由於咱們的 DNS - F 是部署在每臺主機上的,而後提供一個緩存的功能。帶來的效果就是:

  • 平均解析延遲會從以前的200毫秒降低到如今的1毫秒;


緩存命中率會從以前的90%上升到99.8%,90%是用 CoreDNS 原生的那個 Cache,99.8%是在這個 Cache 的組件下作了優化以後的效果;

  • 解析失敗率是從以前的0.1%降低到0%;

這裏再總結一下項目落地的技術價值:

第一,提供了基於 DNS 服務發現的能力,消除異構系統之間互相調用的障礙。

第二,填補了沒有內部域名解析能力的空白。

第三,解決咱們上面說的內部服務調用面臨的挑戰:延時大、解析不許、不支持多種負載均衡策略、故障牽引慢。

第四,優化外部域名的解析,屏蔽 LocalDNS 的故障。

落地規模是:DNS - F 覆蓋率100%,完成 Taf 和 Eureka 註冊中心的數據同步。

後續規劃

LocalDNS:

解決公共 DNS 節點位置影響域名解析準確性的問題;

解決內部使用公共 DNS 不穩定的問題;

優化內外網解析;

精準調度:

解決全球 DNS 節點生效慢的問題。

 

原文連接

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索