如何打造真正可動態(tài)擴(kuò)展的服務(wù)架構(gòu)
在互聯(lián)網(wǎng)應(yīng)用領(lǐng)域,服務(wù)的動態(tài)性需求十分常見,這就對服務(wù)的自動發(fā)現(xiàn)和可動態(tài)擴(kuò)展提出了很高的要求。
Docker 的出現(xiàn),以及微服務(wù)架構(gòu)的興起,讓眾多開源項目開始關(guān)注在松耦合的架構(gòu)前提下,如何基于 Docker 實現(xiàn)一套真正可動態(tài)擴(kuò)展的服務(wù)架構(gòu)。
基本需求
基本的需求包括:
- 服務(wù)啟動后要能自動被發(fā)現(xiàn)(vs 傳統(tǒng)需要手動進(jìn)行注冊);
- 負(fù)載要能動態(tài)在可用的服務(wù)實例上進(jìn)行均衡(vs 傳統(tǒng)需要靜態(tài)寫入配置);
- 服務(wù)規(guī)模要方便進(jìn)行快速調(diào)整(vs 傳統(tǒng)需要較長時間的手動調(diào)整)。
相關(guān)項目
服務(wù)發(fā)現(xiàn)
服務(wù)發(fā)現(xiàn)的項目已經(jīng)有不少,包括之前介紹的 consul,以及 skydns、serf、以及主要關(guān)注一致性的強(qiáng)大的 zookeeper 等。
這些項目各有優(yōu)缺點(diǎn),功能上大同小異,都是要通過某種機(jī)制來獲取服務(wù)信息,然后通過維護(hù)一套(分布式)數(shù)據(jù)庫來存儲服務(wù)的信息。這也是為什么 etcd 受到大家關(guān)注和集成。
在這里,選用 HashiCorp 公司的 consul 作為服務(wù)發(fā)現(xiàn)的管理端,它的簡介可以參考 這里。
服務(wù)注冊
服務(wù)注冊的手段有很多,當(dāng)然,從發(fā)起方是誰可以分為兩大類,主動注冊還是被動探測。
主動注冊,顧名思義,服務(wù)啟動后,向指定的服務(wù)發(fā)現(xiàn)管理端的 API 發(fā)送請求,給出自身的相關(guān)信息。這樣做,對管理端的要求簡單了很多,但意味著服務(wù)自身要完成注冊工作,并且極端情況下,管理端比較難探測出真正存活的服務(wù)。
被動探測,則是服務(wù)發(fā)現(xiàn)管理端通過某種機(jī)制來探測存活的服務(wù)。這樣可以獲取真實的服務(wù)情況,但如何探測是個很難設(shè)計的點(diǎn),特別當(dāng)服務(wù)類型比較復(fù)雜的時候。
以上兩種,都對網(wǎng)絡(luò)連通性要求較高。從短期看,主動注冊方式會比較容易實現(xiàn)一些,應(yīng)用情形更廣泛;但長期維護(hù)上,被動探測方式應(yīng)該是更高效的設(shè)計。
這里,我們選用 gliderlabs 的 registrator,它可以通過跟本地的 docker 引擎通信,來獲取本地啟動的容器信息,并且注冊到指定的服務(wù)發(fā)現(xiàn)管理端。
配置更新
服務(wù)被調(diào)整后,負(fù)載均衡器要想動態(tài)重新分配負(fù)載,就需要通過配置來獲取更新。這樣的方案也有不少,基本上都是要安裝一些本地 agent 來監(jiān)聽服務(wù)發(fā)現(xiàn)管理端的信息,生成新的配置,并執(zhí)行更新命令。
HashiCorp 公司 的consul-template,可以通過監(jiān)聽 consul 的注冊信息,來完成本地應(yīng)用的配置更新。
負(fù)載均衡
負(fù)載均衡對性能要求很高,其實并不是軟件所擅長的領(lǐng)域,但軟件方案勝在成本低、維護(hù)方便。包括 lvs、haproxy 都是很優(yōu)秀的設(shè)計方案。
這里,我們選用 nginx。nginx 不僅是個強(qiáng)大的 web 代理服務(wù)器,同時在負(fù)載均衡方面表現(xiàn)也不俗。更關(guān)鍵的,新版本的 nginx 對在線升級支持做到了極致。實時配置更新更是不在話下,可以保證服務(wù)的連續(xù)性。
實驗過程
準(zhǔn)備工作
首先,從 這里 下載模板文件。
主要內(nèi)容如下:
- #backend web application, scale this with docker-compose scale web=3
- web:
- image: yeasy/simple-web:latest
- environment:
- SERVICE_80_NAME: http
- SERVICE_NAME: web
- SERVICE_TAGS: backend
- ports:
- - "80"
- #load balancer will automatically update the config using consul-template
- lb:
- image: yeasy/nginx-consul-template:latest
- hostname: lb
- links:
- - consulserver:consul
- ports:
- - "80:80"
- consulserver:
- image: gliderlabs/consul-server:latest
- hostname: consulserver
- ports:
- - "8300"
- - "8400"
- - "8500:8500"
- - "53"
- command: -data-dir /tmp/consul -bootstrap -client 0.0.0.0
- # listen on local docker sock to register the container with public ports to the consul service
- registrator:
- image: gliderlabs/registrator:master
- hostname: registrator
- links:
- - consulserver:consul
- volumes:
- - "/var/run/docker.sock:/tmp/docker.sock"
- command: -internal consul://consul:8500
如果沒有安裝 docker 和 docker-compose,需要先進(jìn)行安裝,以 ubuntu 系統(tǒng)為例。
- $ curl -sSL https://get.docker.com/ | sh
- $ sudo pip install docker-compose
執(zhí)行
docker-compose 模板所在目錄,執(zhí)行
- $ sudo docker-compose up
相關(guān)鏡像即可自動被下載,下載完畢后,容器就啟動起來了。
訪問 http://localhost 可以看到一個 web 頁面,提示實際訪問的目標(biāo)地址。
多次刷新,可以看到目標(biāo)地址沒有變化,這是因為,目前我們只有一個 web 后端服務(wù)器。
- 2015-08-18 03:37:58: 6 requests from <LOCAL: 172.17.1.150> to WebServer <172.17.1.148>
調(diào)整后端為 3 個服務(wù)器。
- $ sudo docker-compose scale web=3
然后,再次訪問 http://localhost,多次刷新,可以看到訪問的實際目標(biāo)地址發(fā)生了變化,新啟動的 web 服務(wù)器被自動注冊,并且 nginx 自動對它們進(jìn)行了負(fù)載均衡。
- 2015-08-18 03:37:58: 6 requests from <LOCAL: 172.17.1.150> to WebServer <172.17.1.148>
- 2015-08-18 03:38:17: 5 requests from <LOCAL: 172.17.1.150> to WebServer <172.17.1.152>
- 2015-08-18 03:38:20: 5 requests from <LOCAL: 172.17.1.150> to WebServer <172.17.1.153>
博文出處:http://blog.csdn.net/yeasy/article/details/47749725