為什么選用Nacos?虎牙直播微服務(wù)改造實(shí)踐
相比文字和圖片,直播提供了人與人之間更豐富的溝通形式,其對平臺(tái)穩(wěn)定性的考驗(yàn)很大,那么倡導(dǎo)“以技術(shù)驅(qū)動(dòng)娛樂”的虎牙直播如何在技術(shù)上賦能娛樂。
本文將分為如下幾個(gè)部分介紹虎牙在 DNS、服務(wù)注冊、CMDB 和服務(wù)配置中心等方面的實(shí)踐:
- 為什么選用 Nacos
- DNS-F 的技術(shù)價(jià)值和應(yīng)用場景
- 服務(wù)注冊的實(shí)踐
- CMDB 的應(yīng)用和實(shí)踐
- 服務(wù)配置的實(shí)踐
- Nacos 改造和升級(jí)總結(jié)
為什么選用 Nacos
虎牙關(guān)注 Nacos 是從 v0.2 開始的(***版本:Pre-GA v0.8),我們也參與了社區(qū)的建設(shè),可以說是比較早期的企業(yè)用戶。
Nacos 是一個(gè)更易于幫助構(gòu)建云原生應(yīng)用的動(dòng)態(tài)服務(wù)發(fā)現(xiàn)、配置和服務(wù)管理平臺(tái),提供注冊中心、配置中心和動(dòng)態(tài) DNS 服務(wù)三大功能。
首先,在虎牙的微服務(wù)場景中,起初有多個(gè)注冊中心,每一個(gè)注冊中心服務(wù)于某一部分微服務(wù),缺少一個(gè)能融合多個(gè)注冊中心,并把他們逐一打通,然后實(shí)現(xiàn)一個(gè)能管理整個(gè)微服務(wù)體系的大的注冊中心。
以下內(nèi)容摘自我們考慮引入 Nacos 時(shí),在服務(wù)注冊中心方案上的選型對比:
Nacos 提供 DNS-F 功能, 可以與 K8S、Spring Cloud 和 Dubbo 等多個(gè)開源產(chǎn)品進(jìn)行集成,實(shí)現(xiàn)服務(wù)的注冊功能。
其次,在服務(wù)配置中心方案的選型過程中,我們希望配置中心和注冊中心能夠打通,這樣可以省去我們在微服務(wù)治理方面的一些投入。
因此,我們也同步比較了一些服務(wù)配置中心的開源方案:
例如 Spring Cloud Config Server、Zookeeper 和 ETCD,總體評(píng)估下來,基于我們微服務(wù)體系現(xiàn)狀以及業(yè)務(wù)場景,我們決定使用 Nacos 作為我們服務(wù)化改造中服務(wù)注冊和服務(wù)發(fā)現(xiàn)的方案。
使用過程中,我們發(fā)現(xiàn),隨著社區(qū)版本的不斷更新和虎牙的深入實(shí)踐,Nacos 的優(yōu)勢遠(yuǎn)比我們調(diào)研過程中發(fā)現(xiàn)的更多。
接下來,我將圍繞 DNS-F、Nacos-Sync、 CMDB 和負(fù)載均衡四個(gè)方面來分享虎牙的實(shí)踐。
DNS-F 的技術(shù)價(jià)值和應(yīng)用場景
DNS-F 的技術(shù)價(jià)值
Nacos 提供的 DNS-F 功能的***個(gè)技術(shù)價(jià)值在于,彌補(bǔ)了我們內(nèi)部微服務(wù)沒有一個(gè)全局動(dòng)態(tài)調(diào)度能力的空白。
剛才提到,虎牙有多個(gè)微服務(wù)體系,但并沒有一個(gè)微服務(wù)具備全局動(dòng)態(tài)調(diào)度的能力,因?yàn)樗鼈兏髯远际仟?dú)立的。
目前,我們通過 Nacos 已經(jīng)融合了四個(gè)微服務(wù)體系的注冊中心,最終目標(biāo)是把所有的微服務(wù)都融合在一起,實(shí)現(xiàn)全局動(dòng)態(tài)調(diào)動(dòng)的能力。
第二,DNS-F 解決了服務(wù)端端到端面臨的挑戰(zhàn),即延時(shí)大、解析不準(zhǔn)、故障牽引慢的問題。
如何去理解呢?當(dāng)內(nèi)部有多個(gè)微服務(wù)體系的時(shí)候,每一個(gè)體系的成熟度是不同的。
例如,有一些微服務(wù)框架對同機(jī)房或 CMDB 路由是不支持的,當(dāng)一個(gè)服務(wù)注冊到了多個(gè) IDC 中心,去調(diào)用它的服務(wù)的時(shí)候,即便是同機(jī)房,也可能調(diào)用到一個(gè)不是同機(jī)房的節(jié)點(diǎn)。
這樣就會(huì)無端的造成服務(wù)的延時(shí)和解析不準(zhǔn)。即使我們基于 DNS 做一些解析的優(yōu)化,但仍然無法完全解決服務(wù)的延時(shí)和解析不準(zhǔn)。
這是因?yàn)?DNS 都是 IP 策略的就近解析,無法根據(jù)服務(wù)的物理狀態(tài)、物理信息進(jìn)行路由。
此外,當(dāng)一個(gè)核心服務(wù)出現(xiàn)問題,如果缺少一個(gè)融合了多個(gè)調(diào)用方和被調(diào)用方的信息的統(tǒng)一的注冊中心,就很難去準(zhǔn)確判斷如何去牽引,從而導(dǎo)致故障牽引慢。
有了 Nacos 后,就可以接入一個(gè)統(tǒng)一的注冊中心以及配置中心,去解決這些問題。(目前,虎牙還在微服務(wù)體系的改造過程中,未完全實(shí)現(xiàn)統(tǒng)一的注冊中心)
第三,提供專線流量牽引能力?;⒀赖暮诵臋C(jī)房的流量互通,是使用專線來實(shí)現(xiàn)的。專線的特性就是物理建設(shè)的,而且我們的專線建設(shè)可能不像 BAT 那么大。
例如我們專線容量的冗余只有 50%,假設(shè)某個(gè)直播異?;鸨?,突發(fā)流量高于平常的兩百倍,超過了專線的建設(shè)能力,這時(shí)候一個(gè)服務(wù)就有可能會(huì)導(dǎo)致全網(wǎng)故障。
但是,通過全局的注冊中心和調(diào)動(dòng)能力,我們就可以把流量牽引到其他地方,例如遷移到公網(wǎng),甚至牽引到一個(gè)不存在的地址,來平衡一下。即便某個(gè)服務(wù)出現(xiàn)問題,也不會(huì)影響我們的全局服務(wù)。
第四,支持服務(wù)端的多種調(diào)度需求,包括同機(jī)房路由、同機(jī)器路由,以及同機(jī)架路由,Nacos 都可以去做適配。
此外,基于 Nacos 的 DNS-F 功能,我們還實(shí)現(xiàn)了加速外部域名解析和服務(wù)故障牽引秒級(jí)生效。
DNS-F 的應(yīng)用場景
這張圖是 Nacos DNS-F 的一個(gè)具體實(shí)現(xiàn),實(shí)際上是攔截了 OS 層的 DNS 請求。
如果經(jīng)過 DNS 的域名是內(nèi)部服務(wù),它就會(huì)從 Nacos Server 獲取結(jié)果,如果不是,就會(huì)轉(zhuǎn)發(fā)到其它的 LocalDNS 進(jìn)行解析。
以數(shù)據(jù)庫高可用的應(yīng)用場景為例,我們的數(shù)據(jù)庫切換效率比較低,依賴業(yè)務(wù)方修改配置,時(shí)效不確定,通常需要 10 分鐘以上(備注:我們的數(shù)據(jù)庫實(shí)際上已經(jīng)實(shí)現(xiàn)了主備的功能,但當(dāng)一個(gè)主服務(wù)出現(xiàn)問題的時(shí)候,總是要去切換IP。)切換 IP 的過程中,依賴運(yùn)維和開發(fā)的協(xié)作,這是一個(gè)比較長的過程。
引入 DNS 后,當(dāng)主出現(xiàn)問題的時(shí)候,就可以很快的用另外一個(gè)主的 IP 來進(jìn)行替換,屏蔽故障,而且節(jié)點(diǎn)的故障檢測和故障切換都可以自動(dòng)完成,并不依賴運(yùn)維和開發(fā)的協(xié)作,節(jié)省了時(shí)間。
當(dāng)然,這個(gè)場景的解法有很多,比如說使用 MySQL - Proxy 也可以去解這個(gè)問題,但我們的 MySQL - Proxy 還在建設(shè)中,想盡快的把這個(gè)問題解決,所以采用了 DNS 的方式。
下面我們再著重分享下基于 DNS-F 對 LocalDNS 的優(yōu)化?;⒀肋€沒有去建設(shè)自己的 LocalDNS,大部分使用的是一些公共的 DNS,大致有以下這些組成。
這種組成方式會(huì)存在一個(gè)問題:假設(shè)服務(wù)突然一下崩潰后,之后服務(wù)又馬上正常了,這種情況我們無法重現(xiàn)去找到崩潰原因。
因?yàn)楹芏鄨鼍跋?,是一個(gè)公共 DNS 的請求超時(shí)導(dǎo)致的,甚至一個(gè)解析失敗導(dǎo)致的,在那一刻,因?yàn)闊o法保留現(xiàn)場的,所以就發(fā)現(xiàn)不了問題。
以我們的監(jiān)測數(shù)據(jù)來看,DNS 解析錯(cuò)誤的比例達(dá)到 1% 左右,超時(shí)比例將更高。
意思是在使用公共 DNS 的情況下,服務(wù)有 1% 的幾率是會(huì)超時(shí)或失敗,如果服務(wù)沒有做好容錯(cuò),就會(huì)出現(xiàn)異常。
同時(shí),一些公共 DNS 解析的延時(shí)都是不定的,比如在亞馬遜上一些比較不好的節(jié)點(diǎn),它的延時(shí)會(huì)比較高,平均超過三四十毫秒。
然后我們基于 DNS-F 對 LocalDNS 做了一些優(yōu)化,優(yōu)化結(jié)果如下:
- 平均解析時(shí)間從之前的超過兩百毫秒降低到兩毫秒以下。
- 緩存***率從 92% 提升到了 99% 以上。
- 解析失敗率之前是 1%,現(xiàn)在基本上沒有了。
優(yōu)化的效果也體現(xiàn)在我們的風(fēng)控服務(wù)上,平均延遲下降 10ms,服務(wù)超時(shí)比例下降 25%,降低了因延遲或服務(wù)超時(shí)導(dǎo)致的用戶上傳的圖片或文字違規(guī)但未被審核到的風(fēng)險(xiǎn)。
服務(wù)注冊的實(shí)踐
虎牙的核心業(yè)務(wù)是跑在 Tars(騰訊開源的一款微服務(wù)框架) 上的。
Tars 主要是支持 C++,但對 Java、PHP 等開發(fā)語言的支持力度比較差,這就使得我們非 C++ 的業(yè)務(wù)方去調(diào)用它就會(huì)很別扭。
引入 Nacos 以后,我們通過 Nacos 支持的 DNS 協(xié)議來實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)過程中對全語言的支持。
當(dāng)然,Nacos 不只是一個(gè)注冊中心,它具備了融合多個(gè)數(shù)據(jù)中心的能力,支持多數(shù)據(jù)源的同步。
例如,我們目前已經(jīng)支持了 Taf(虎牙內(nèi)部的一個(gè)重要微服務(wù)體系)、Nacos 自身、ZooKeeper、以及 K8S 上一些服務(wù)注冊的同步。
同時(shí),基于 Nacos 集群的雙向同步功能(Nacos-Sync),我們實(shí)現(xiàn)了國內(nèi)的兩個(gè)可用區(qū),以及國外的多個(gè)可用區(qū)之間的數(shù)據(jù)值同步,最終實(shí)現(xiàn)了一處注冊、多地可讀。
Nacos-Sync 是事件機(jī)制,即同步任務(wù)通過事件觸發(fā),可以靈活地開啟和關(guān)閉你要同步的任務(wù),然后根據(jù)服務(wù)變化事件觸發(fā)監(jiān)聽,保證實(shí)時(shí)性,***通過定時(shí)的全量突發(fā)同步事件,保證服務(wù)數(shù)據(jù)的最終一致。
同時(shí),Nacos-Sync 也支持服務(wù)心跳維持,即多個(gè)數(shù)據(jù)中心的心跳,可以使用 Nacos-Sync 代理來實(shí)現(xiàn)遠(yuǎn)端同步。此外,也支持心跳與同步任務(wù)綁定,便于靈活控制。
由于 Taf 上有數(shù)萬個(gè)注冊服務(wù),同步的量特別大,所以我們在 Nacos-Sync 做了一些改造,通過任務(wù)分片來實(shí)現(xiàn)數(shù)萬服務(wù)同步的可用性保障。
改造步驟是先以服務(wù)為粒度定義任務(wù),然后在多個(gè)分片上分散任務(wù)負(fù)載,***以單分片多副本來保證任務(wù)可用性。
對接 CMDB,實(shí)現(xiàn)就近訪問
在服務(wù)進(jìn)行多機(jī)房或者多地域部署時(shí),跨地域的服務(wù)訪問往往延遲較高,一個(gè)城市內(nèi)的機(jī)房間的典型網(wǎng)絡(luò)延遲在 1ms 左右,而跨城市的網(wǎng)絡(luò)延遲,例如上海到北京大概為 30ms。
此時(shí)自然而然的一個(gè)想法就是能不能讓服務(wù)消費(fèi)者和服務(wù)提供者進(jìn)行同地域訪問。
Nacos 定義了一個(gè) SPI 接口,里面包含了與第三方 CMDB 約定的一些方法。
用戶依照約定實(shí)現(xiàn)了相應(yīng)的 SPI 接口后,將實(shí)現(xiàn)打成 Jar 包放置到 Nacos 安裝目錄下,重啟 Nacos 即可讓 Nacos 與 CMDB 的數(shù)據(jù)打通。
在實(shí)際的落地過程中,我們是在 DNS-F 接入 Taf,在 DNS-F 上實(shí)現(xiàn) Taf 的中控接口,無縫對接 Taf 的 SDK。
DNS-F 提供緩存負(fù)載均衡和實(shí)例信息,Nacos 則提供負(fù)載均衡信息的查詢接口。
服務(wù)配置的實(shí)踐
虎牙的域名(www.huya.com)會(huì)接入華南、華中、華北多個(gè) IDC 機(jī)房,每個(gè)機(jī)房都會(huì)建設(shè)一個(gè) Nginx 去做負(fù)載均衡,經(jīng)過負(fù)載均衡的流量會(huì)通過專線返回到我們的后端服務(wù)器上。
在這個(gè)過程中,如果我們?nèi)バ薷囊粋€(gè)在中間的配置,需要下發(fā)到多個(gè)機(jī)房的上百個(gè)負(fù)責(zé)負(fù)載均衡的機(jī)器上。
如果出現(xiàn)配置下發(fā)不及時(shí),或下發(fā)配置失敗,極大可能會(huì)出現(xiàn)故障,同時(shí),負(fù)責(zé)均衡服務(wù)的機(jī)器對彈性能力的要求較高,在業(yè)務(wù)高峰如果不能快速擴(kuò)容,容易出現(xiàn)全網(wǎng)故障。
傳統(tǒng)的配置下發(fā)方式是通過服務(wù)端下發(fā)文件更新配置,更新配置生效時(shí)間長,由于需要預(yù)先知道負(fù)責(zé)均衡集群的機(jī)器信息,擴(kuò)縮容需要等元信息同步以后才能接入流量,擴(kuò)容流量的接入時(shí)間較長。
引入 Nacos 后,我們采用了配置中心監(jiān)聽方式,通過客戶端主動(dòng)監(jiān)聽配置更新,配置便可秒級(jí)生效,新擴(kuò)容服務(wù)主動(dòng)拉取全量配置,流量接入時(shí)長縮短 3 分鐘+。
Nacos 改造和升級(jí)總結(jié)
引入 Nacos 的過程中,我們所做的改造和升級(jí)總結(jié)如下:
①在 DNS-F 上,我們增加了對外部域名的預(yù)緩存的支持,Agent 的監(jiān)控?cái)?shù)據(jù)對接到公司的內(nèi)部監(jiān)控,日志輸出也對接到內(nèi)部的日志服務(wù),然后和公司的 CMDB 對接,并實(shí)現(xiàn)了 DNS-F Cluster 集群。
我們之所以去構(gòu)建一個(gè) DNS-FCluster 集群,是為了避免內(nèi)存、硬盤或版本問題導(dǎo)致的 DNS 服務(wù)無效,有了 DNS-F Cluster 集群,當(dāng)本地 Agent 出現(xiàn)問題的時(shí)候,就可以通過集群去代理和解析 DNS 請求。
②在 Nacos-Sync 上,我們對接了 TAF 注冊服務(wù)和 K8S 注冊服務(wù),以及解決了多數(shù)據(jù)中心環(huán)形同步的問題。
③在 Nacos CMDB 上,我們對 Nacos CMDB 進(jìn)行了擴(kuò)展,對接了虎牙自己的 CMDB,并對接了內(nèi)部的負(fù)載均衡策略。