「微服務」 (Microservice) 是今年特別熱的一個概念,Martin Fowler 的文章 對微服務做了詳細的介紹。簡而言之,微服務鼓勵用戶把功能拆分以細粒度的服務接口暴露出來,並經過 REST 服務或輕量級消息隊列集成。在微服務架構裏,一個業務的實現,可能由不一樣的功能單元組合而實現。html
在 AVOS Cloud,咱們提供數據存儲、統計、實時通訊等不一樣功能的服務,在實現上,這些功能須要共用基礎設施,有的服務自己也根據業務性質的不一樣拆分功能模塊,咱們目前就是以這種「微服務」架構思路來實現拆分。有句話說,if you cannot split, you cannot scale.git
以實時通訊服務爲例,根據功能角色的不一樣,咱們有這樣一些模塊:github
模塊間的集成,根據業務的特性分別使用 Slacker 遠程調用框架和 Kestrel 消息隊列。
對於可能耗時較大的任務,咱們經過 Kestrel 隊列放到後臺執行,避免阻塞前臺服務,影響吞吐量。而另外一些須要實時的集成,則使用 Slacker 遠程調用實現多個進程間的通訊。apache
Slacker 是一個專門爲 Clojure 語言設計的遠程調用框架,利用 Slacker 你能夠暴露一個 或多個 Clojure 的 namespace 供遠程調用。在客戶端,Slacker 利用 Clojure 宏 的特性,保持遠程調用和本地調用的代碼徹底一致,這樣本地和遠程調用的切換隻要更改一個 (require) 便可實現,把框架對業務代碼的侵入降到最低。此外,Slacker 使用二進制序列化 nippy,在網絡鏈接層面使用異步複用,同時在超時方面也作了良好的控制。服務器
以上的基礎設施幫助咱們良好地拆分模塊,爲下一步的擴展提供了可能。網絡
長鏈接服務器是實時通訊的功能核心,它的瓶頸在內存和 CPU,能夠經過增長部署來達到線性擴展。隨着業務量的增長和硬件資源的整合,它可能會面臨較頻繁的部署變化,另外它也須要有能經過新增部署來快速平滑高峯壓力的能力。基於 Pub/Sub 抽象 的消息隊列對此有良好的支持,但這對咱們以 RPC 爲核心的集成方式提出了新的要求,依賴模塊也能快速響應服務部署的變化:咱們不可能在新增某個服務部署後修改每一個依賴的配置再逐一重啓。架構
在這方面,咱們利用了 Slacker Cluster 框架 。他的核心思想是在部署和服務間增長一層抽象:對於服務的消費者而言,只需聲明本身所依賴的服務,而無需靜態地瞭解進程的地址。框架
全部的服務提供者將本身可以提供的服務註冊在 Zookeeper 集羣裏,並將部署地址註冊爲 Ephemeral 節點。Ephemeral 節點在建立它的鏈接斷後會自動刪除,這樣當一個部署下線後,它相應的節點也會自動刪除。運維
# Zookeeper 目錄結構 ls /slacker/example-cluster/namespaces/ [my.serviceA, my.serviceB] ls /slacker/example-cluster/namespaces/my.serviceA [192.168.1.100:2104, 192.168.1.101:2014...]
全部服務的客戶端會 watch 本身感興趣的 Zookeeper 節點,而部署變化時,全部的客戶端都會獲得通知,進而刷新服務列表,將流量引向新的節點。異步
在實時通訊服務中,Router 服務會經過這個 RPC 機制輪詢全部在線的長鏈接服務器,記錄他們實時的運行狀態。全部的用戶設備並不是直接鏈接到固定的長鏈接服務器,而是先詢問 Router,由後者分配一臺壓力較輕的實例。當有新的長鏈接服務器部署後,Router 收到通知,新的鏈接將優先鏈接這個新進程。此外,監控和數據收集的服務也會自動地把新實例加入管理範圍。
有了這樣一套服務發現機制,咱們就能夠對整個架構中的任意模塊隨時增減部署,保證服務能夠以健康的狀態運行。將來,咱們還會集成雲主機的提供商的 API,來實現基礎設施的自動化:當系統壓力達到閥值時,雲主機自動分配新的資源自動開機,jenkins 自動部署,加上現有的服務發現機制,實現 0 手工操做。這將是雲服務運維的新篇。