Yelp研發實踐:使用服務拆分單塊應用
原文 http://www.infoq.com/cn/news/2015/03/yelp-soa-break-monoliths
Yelp工程師團隊 表示,面對團隊和代碼庫規模不斷增長的情況,他們通過實踐向面向服務架構遷移,得以使開發過程同步具備擴展能力,并且保持了快速的軟件交付。這一切取決于以下因素,包括對團隊灌輸分布式系統的理念,創建一組基本的服務設計原則,定義服務接口規范,實現可擴展的測試方法,將對數據存儲的訪問封裝到各自的服務接口中,同時部署一個健壯的服務發現方案。
Yelp工程師團隊在 博客中表明 他們很看重快速交付代碼的能力。他們需要不斷地進行生產系統的變更,而且這種頻繁變更需要常態化保持,即便開發團隊已經增長到300人以上,Python 代碼庫規模也超過了幾百萬行。能夠確保這樣迭代速度的核心因素恰恰就是轉向了面向服務的架構(SOA)。在過去的三年里,Yelp工程師團隊已經研發并在生產環境部署了超過七十個各式服務。
Yelp工程師博客提出,構建面向服務的架構會迫使程序員應對分布式系統需要面臨的 現實挑戰 ,例如需要面對系統部分失效以及代碼由不同的團隊開發的情況。Yelp嘗試采用一些手段去緩解這些問題,例如參考 Netflix 和 推ter ,實現并管理一套底層的基礎研發平臺。然而,Yelp工程師團隊還是提出,程序員只能靠自己去理解系統需要面對的這些現實問題,任何其他東西都幫不上忙。
Yelp工程師團隊倡導用多種技術手段在團隊間擴散知識,包括建立一套編寫和維護服務的 基本準則 ,建立每周服務專題的例會,程序員可以自愿參加并提問探討,同時通過咨詢有過慘痛教訓的人,從而幫助工程師團隊從錯誤中汲取經驗教訓。
Yelp的大多數內部服務都是以HTTP的方式暴露接口,并且傳遞的數據結構采用JSON,這樣既有優點也有缺點:
我們使用HTTP和JSON是一種折中的選擇。使用標準化HTTP協議有一個巨大的好處,那就是可以使用業內成熟優秀的工具去調試、緩存和負載均衡。而最顯著的缺點是在不考慮數據接口實現的情況下,沒有標準的方案去定義服務的接口(這一點與Thrift這樣的技術不同)。這樣使得定義和檢查接口變得很困難,并且會導致很糟糕的缺陷(“我原以為你的服務應該返回‘username’字段?”)
Yelp工程師團隊通過使用 Swagger 解決了以上問題。Swagger是基于一套JSON Schema標準構建的,它針對HTTP/JSON服務接口提供統一的文檔描述語言。 Swagger UI 則可以用來提供一個所有服務的集中式目錄,允許所有Yelp開發團隊成員檢索已有的服務,避免重復發明輪子。
Yelp工程師在博客上同時探討說,對服務自身的測試應當采用標準的方法,包括單元測試和使用模擬對象集成測試。然而,跨服務的測試可能需要復雜的編排協調。Yelp使用 Docker 容器快速提供私有的服務測試實例,包括數據庫實例。核心的想法是服務的研發團隊有責任發布自身服務的Docker鏡像,供其他服務開發人員可以將這些服務置為依賴項,并在對其他服務進行驗收測試時使用。
Yelp服務中有很大一部分需要對數據進行持久化,工程師團隊使用了MySQL、Cassandra和ElasticSearch的組合。 Yelp工程師在博客上說,無論數據庫存儲選用什么產品,底層的實現細節只需要服務自身了解。這種做法能夠使服務作者擁有長期的靈活度,可以隨意更改底層數據的表述方式,甚至是改變整個數據庫。
面向服務架構的一個核心問題是如何發現其他服務實例的位置。Yelp使用了AirBnB的 SmartStack 服務發現機制,將服務發現的問題從應用自身中脫離出來,交由其他獨立進程來解決。SmartStack包含兩個進程; Nerve 用于服務注冊,Synapse用于服務發現。Yelp研發團隊在博客上說每一個服務節點都運行著一個綁定本地節點的Synapse HAProxy實例。HAProxy負載均衡會讀取Nerve在遠程 Zookeeper 上服務注冊的信息,并動態配置服務路由。這樣一來,本地的負載均衡器可以將服務請求路由到其他健康的服務實例上,從而使一個服務可以連接其他額外的服務。
Yelp工程師在博文結束時表示下一代名為 Paasta 的服務平臺研發工作已經開始,項目會使用 Apache Mesos 與 Marathon 框架的組合,在集群機器之間分配容器化的服務實例。關于這個項目的更詳細的內容將于今年晚些時候在 博客上 發布。
在Yelp官方博客上,大家可以找到更多關于 Yelp開發團隊使用服務分解單塊應用 的細節。
查看英文原文: Yelp Engineering: Using Services to Break Down a Monolith
感謝趙震一對本文的審校。