演講 | 葉靖(又拍云系統(tǒng)開發(fā)工程師)
整理 | 不離
近日,又拍云Open Talk No.24在廣州落幕,本次Open Talk的主題是“Docker與微服務(wù)的架構(gòu)實(shí)踐”,又拍云葉靖在活動(dòng)中分享了“基于ngx_lua的動(dòng)態(tài)服務(wù)路由方案”,詳細(xì)介紹了又拍云在這方面積累的經(jīng)驗(yàn)。
點(diǎn)擊文末的“閱讀原文”,獲取又拍云Open Talk No.24 (Docker與微服務(wù)架構(gòu)實(shí)踐)的現(xiàn)場PPT與視頻。
以下是葉靖的分享全文。
大家好,我叫葉靖,來自又拍云,主要負(fù)責(zé)云處理,剛才有老師給大家介紹了唯品會(huì)容器化平臺(tái)的整個(gè)架構(gòu),其實(shí)又拍云也在做這樣一件事情,這從另一方面可以理解成這個(gè)三件套已經(jīng)廣泛地被大家接受了,如果大家需要做容器化的時(shí)候,可以借鑒一下今天分享的內(nèi)容。
我今天介紹的是 基于ngx_lua的動(dòng)態(tài)服務(wù)路由, 是整個(gè)容器化過程中的一個(gè)組件。容器化在服務(wù)路由這一塊有很大的挑戰(zhàn),又拍云通過自己的一些方案去解決它,而且這個(gè)方案也會(huì)開源出來,如果大家以后也碰到這樣的問題,可以直接用這個(gè)方案。
如何做到服務(wù)的zero down_time的更新
在更新服務(wù)的時(shí)候,怎么能做到讓自己的服務(wù)不斷掉, 又拍云做更新的時(shí)候,不允許有失敗,如果說因?yàn)槲覀兊氖《鴮?dǎo)致請(qǐng)求失敗,即使你的請(qǐng)求非常少,首先從口碑上就很不好;另外一個(gè)原因:如果造成了事故,是要賠錢的。這也是我們做動(dòng)態(tài)服務(wù)路由的重要原因。
說到服務(wù)路由,大家都會(huì)想到三個(gè)方面:
服務(wù)注冊(cè)、服務(wù)發(fā)現(xiàn)、負(fù)載均衡,服務(wù)注冊(cè)說的是服務(wù)提供者在起來的時(shí)候,得去服務(wù)發(fā)現(xiàn)注冊(cè)一下,以表明我提供了的服務(wù)、端口、IP是多少,服務(wù)名又是什么。
服務(wù)發(fā)現(xiàn)就是一個(gè)集中管理服務(wù)的地方,上面記錄了有哪些服務(wù),它們?cè)谀男┑胤健?/p>
負(fù)載均衡,因?yàn)橛泻芏嗤瑯拥娜萜魈峁┝送瑯拥囊粋€(gè)服務(wù),怎么在這些容器里做負(fù)載均衡,也是要考慮的。
服務(wù)發(fā)現(xiàn) 有很多方案,ETC跟Consul算是后起之秀,比較常見。Zookeeper是一個(gè)比較老牌的開源項(xiàng)目,比較成熟,對(duì)資源的要求比較高,相對(duì)比較強(qiáng)大一點(diǎn)。Consul不但支持KV存儲(chǔ),還有原生的服務(wù)監(jiān)控、多數(shù)據(jù)中心、DNS功能等,所以我們選了Consul這個(gè)方案。
負(fù)載均衡 也是有很多方案,比如說Nginx,LVS擴(kuò)展起來非常難;再高級(jí)一點(diǎn)的有HA_PROXY,它可以做到高層的,也可以做到基層的,Nginx專注于做HTTP,后續(xù)也支持了TCP。從負(fù)載均衡出發(fā),選擇了Nginx。

如上圖,我們把Nginx和Consul放在一張圖里。為了突出服務(wù)這一塊,我把一些跟服務(wù)不太有關(guān)系的都省略掉了。我們基于Mesos、Docker還有Marathon做了服務(wù)管理。其中有一個(gè)服務(wù)是特殊的,就是Registrator,它會(huì)通過Docker API在每個(gè)物理機(jī)上起一個(gè)容器,通過Docker API,把容器的狀態(tài)定時(shí)的匯報(bào)給Consul,上面的Nginx是做負(fù)載均衡的,因?yàn)槲覀兊姆?wù)目前來說都是基于Nginx直接到容器里面。
Consul里的服務(wù)如何更新到Nginx?
在這個(gè)圖里面,Nginx到容器這一步是沒有問題的,服務(wù)注冊(cè)到配置文件也是沒有問題的,但是從Consul到Nginx是有問題的,因?yàn)镃onsul有所有的信息,但是這些信息要如何通知給Nginx,一個(gè)新的服務(wù)起來了,或者是一個(gè)服務(wù)掛掉了,這些信息Consul知道了,怎么讓Nginx把有一些有問題的給刪掉,再把一些新寫的給加進(jìn)去,這就是我們要解決的一個(gè)問題。
面臨的問題就是Consul里的服務(wù)如何更新到Nginx,如果解決了這個(gè)問題,剛才那個(gè)圖就已經(jīng)圓滿。
市場上有很多方案來解決這個(gè)問題:
1. Consul_template

監(jiān)聽Consul里的key,會(huì)觸發(fā)執(zhí)行一個(gè)腳本,利用這個(gè)特性的服務(wù),服務(wù)發(fā)生變動(dòng),會(huì)根據(jù)預(yù)先配置好的模板去重新生成配置,這個(gè)就是最后要執(zhí)行的一個(gè)腳本。原理就是這樣:

上圖是一個(gè)例子,比如說一個(gè)模板是這樣的,然后中間都是將來要被渲染的一些變量,如果K/v發(fā)生變動(dòng),模板化生成一份真實(shí)的配置文件,然后再執(zhí)行一個(gè)本地的命令,Nginx -s reload,重新生成配置文件,Reload一下,這樣新的服務(wù)就已經(jīng)生效了。當(dāng)然這樣也有一些 問題: