如何打造真正可動態擴展的服務架構
在互聯網應用領域,服務的動態性需求十分常見,這就對服務的自動發現和可動態擴展提出了很高的要求。
Docker 的出現,以及微服務架構的興起,讓眾多開源項目開始關注在松耦合的架構前提下,如何基于 Docker 實現一套真正可動態擴展的服務架構。
基本需求
基本的需求包括:
- 服務啟動后要能自動被發現(vs 傳統需要手動進行注冊);
- 負載要能動態在可用的服務實例上進行均衡(vs 傳統需要靜態寫入配置);
- 服務規模要方便進行快速調整(vs 傳統需要較長時間的手動調整)。
相關項目
服務發現
服務發現的項目已經有不少,包括之前介紹的 consul,以及 skydns、serf、以及主要關注一致性的強大的 zookeeper 等。
這些項目各有優缺點,功能上大同小異,都是要通過某種機制來獲取服務信息,然后通過維護一套(分布式)數據庫來存儲服務的信息。這也是為什么 etcd 受到大家關注和集成。
在這里,選用 HashiCorp 公司的 consul 作為服務發現的管理端,它的簡介可以參考 這里。
服務注冊
服務注冊的手段有很多,當然,從發起方是誰可以分為兩大類,主動注冊還是被動探測。
主動注冊,顧名思義,服務啟動后,向指定的服務發現管理端的 API 發送請求,給出自身的相關信息。這樣做,對管理端的要求簡單了很多,但意味著服務自身要完成注冊工作,并且極端情況下,管理端比較難探測出真正存活的服務。
被動探測,則是服務發現管理端通過某種機制來探測存活的服務。這樣可以獲取真實的服務情況,但如何探測是個很難設計的點,特別當服務類型比較復雜的時候。
以上兩種,都對網絡連通性要求較高。從短期看,主動注冊方式會比較容易實現一些,應用情形更廣泛;但長期維護上,被動探測方式應該是更高效的設計。
這里,我們選用 gliderlabs 的 registrator,它可以通過跟本地的 docker 引擎通信,來獲取本地啟動的容器信息,并且注冊到指定的服務發現管理端。
配置更新
服務被調整后,負載均衡器要想動態重新分配負載,就需要通過配置來獲取更新。這樣的方案也有不少,基本上都是要安裝一些本地 agent 來監聽服務發現管理端的信息,生成新的配置,并執行更新命令。
HashiCorp 公司 的consul-template,可以通過監聽 consul 的注冊信息,來完成本地應用的配置更新。
負載均衡
負載均衡對性能要求很高,其實并不是軟件所擅長的領域,但軟件方案勝在成本低、維護方便。包括 lvs、haproxy 都是很優秀的設計方案。
這里,我們選用 nginx。nginx 不僅是個強大的 web 代理服務器,同時在負載均衡方面表現也不俗。更關鍵的,新版本的 nginx 對在線升級支持做到了極致。實時配置更新更是不在話下,可以保證服務的連續性。
實驗過程
準備工作
首先,從 這里 下載模板文件。
主要內容如下:
- #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,需要先進行安裝,以 ubuntu 系統為例。
- $ curl -sSL https://get.docker.com/ | sh
- $ sudo pip install docker-compose
執行
docker-compose 模板所在目錄,執行
- $ sudo docker-compose up
相關鏡像即可自動被下載,下載完畢后,容器就啟動起來了。
訪問 http://localhost 可以看到一個 web 頁面,提示實際訪問的目標地址。
多次刷新,可以看到目標地址沒有變化,這是因為,目前我們只有一個 web 后端服務器。
- 2015-08-18 03:37:58: 6 requests from <LOCAL: 172.17.1.150> to WebServer <172.17.1.148>
調整后端為 3 個服務器。
- $ sudo docker-compose scale web=3
然后,再次訪問 http://localhost,多次刷新,可以看到訪問的實際目標地址發生了變化,新啟動的 web 服務器被自動注冊,并且 nginx 自動對它們進行了負載均衡。
- 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