騰訊QQ團隊將于12月4日開源一個服務開發運營框架,叫做毫秒服務引擎(Mass Service Engine in Cluster,MSEC),它集RPC、名字發現服務、負載均衡、業務監控、灰度發布、容量管理、日志管理、Key-Value存儲于一體,目的是提高開發與運營的效率和質量。
毫秒服務引擎的創作沖動和構建經驗,來自QQ后臺團隊超過10年的運營思考。它是一整套解決方案,但也可以拆分來使用其中的監控、Key-Value存儲單品。
典型用戶群體
毫秒服務引擎非常容易搭建和上手,使用它,初學者從零開始開發一個分布式后臺demo并運行起來,只需要2個小時。基本上是一個小時完成框架搭建,一個小時完成開發上線,特別適合互聯網初創公司。
功能與優勢
模塊間訪問采用RPC的方式,開發者不用關注網絡與報文格式,像寫單機程序一樣開發分布式服務。
- 負載自動均衡與容錯,對于單機故障、局部網絡波動等狀況自動應對,服務高可用性。
- 支持C/C++、Java、PHP語言,馬上還會推出支持Python語言;如果選擇C/C++語言,支持協程,兼具開發和運行效率。
- Web化的管理界面,在Web界面完成配置、發布、監控、日志、Key-Value存儲集群管理等所有操作。
- 需要復雜部署的服務器都采用Docker鏡像的方式安裝,使得部署與上手非常容易。
- 相比使用其他開源組件拼湊起來的解決方案,毫秒服務引擎更加的體系化,對團隊的規范更加到位。
毫秒服務引擎設計背景
對于互聯網服務后臺團隊,開發框架的選擇是非常關鍵的問題,10年的海量服務經驗和教訓使得我們團隊深刻認識到:
- 要盡早規范團隊的開發服務框架,避免到了后期,各種開發語言混雜、各類存儲組件充斥、重復編碼、每個模塊形態不統一、文檔缺失、監控癱瘓、人員離職造成大量信息丟失,最后積重難返、痛苦不堪;
- 沒有框架來規范,團隊的隨意性就太大,合作效率就大打折扣,甚至于內耗、反復的挖坑填坑,系統的成敗過于依靠人的意識和水平;
- 規范,不能靠文檔、不能靠勞動紀律、不能靠苦口婆心、不能靠人員意識、不能靠運動式的整頓,要靠技術框架上切實的限制與貼心保護。
如果有機會從零開始定義一個理想的開發框架,我們覺得需要考慮下面9點。
- 同步編碼異步執行。兼顧運行效率和編碼效率,希望代碼寫起來是同步和順序的,而執行的時候是異步的。
- IDL/RPC。支持IDL(接口描述語言)和RPC,減少網絡協議相關的重復工作,協議有比較好的擴展性;遠程調用友好且高效,做到覆蓋主要的開發語言。
- LB。對服務間的調用選路進行統一的管理,對單機故障和網絡波動等常見情況有自動容錯,我們簡稱load balance(LB)。
- 存儲服務化。這個其實和開發框架關系不太緊密,這里提一下,強調存儲應該有統一的組件且由專業的團隊運維,就像共有云一樣。
- 過載保護。框架必須有成熟自帶的過載保護機制,不需要業務開發人員關注或者關注很少。
- 基礎的監控和告警。RPC調用、機器的CPU/網絡活動、任務并發度、時延、進程監控和秒起等基礎信息,要有上報、統計和告警,不需要業務開發人員關注。
- 完整的業務流轉呈現。統一日志,在一個地方能夠清晰的呈現某次業務處理過程的流轉詳細情況:經過了哪些模塊間調用,調用參數是怎樣的,每個模塊處理的重要分支和結果是怎樣的,最好圖形化呈現。支持染色和不同的日志詳細級別。
- 中央總控。整個系統的配置和文檔等重要信息,例如每個模塊有哪些機器,分布在哪些機房、容量冗余情況、模塊間調用關系、訪問控制的配置動態管理甚至電子流,都希望能統一在一個地方Web化的管理起來,并且與運營的系統是直接聯系直接生效的。
- 云調度。容量的自動調度。例如要進行某個運營活動需要大量的擴容,只需要把設備放進去,就能自動的擴縮容。當某個城市機房故障,能夠自動調度容量到其他城市。
毫秒服務引擎架構
整個系統由下面幾部分組成,如圖所示。
-
Tomcat提供Web管理界面,管理的數據保存在MySQL里。
-
LB是名字發現服務和負載均衡,remote_shell是遠程文件傳輸與遠程命令執行服務。
**Log服務器:**提供業務Log的存儲和查詢服務。Log存儲在MySQL表里。
**Monitor服務器:**提供業務上報信息的存儲和查詢服務。業務上報信息存儲在內存里,推薦內存8G~16G。定時dump到磁盤的方式防止數據掉電丟失。
**業務運營服務器:**部署開發框架和業務邏輯代碼,處理業務請求。
**key-value存儲服務:**相對整個框架比較獨立,按需選用。
服務標準化運營
一套互聯網后臺服務的開發和運營涉及非常多的細節。
訪問其他服務模塊,服務端IP如何管理?網絡報文格式是怎樣的?
有哪些配置文件? 用到哪些第三方的庫?
業務邏輯和基礎框架是如何分離的?
對外提供怎樣的網絡接口?怎么對外提供接口API和文檔?
運營機器上的安裝目錄準備怎么安排? 有哪些運維腳本和工具?
應該監控哪些指標?應該記錄哪些日志?
還有很多…
上面種種細節,每個程序員實現起來都有不同的做法。經驗證明,如果后臺各個模塊沒有標準化和規范化,可能導致:同一個團隊開發的服務,千差萬別千奇百怪,負責運維的同事面對的多個模塊“長”的都不一樣,程序框架完全不一樣,安裝目錄亂七八糟,無法規模化的高效運維。
服務的質量完全依賴團隊成員的技能和意識,有的成員可能會做得比較好,配置文件命名易懂、文檔及時更新與代碼保持一致、有對服務做細致的監控上報和日志記錄,提供了運維腳本,但是也有的成員的工作讓人抓狂。
每當有團隊成員離職和工作交接,交接本身就是工作量很大,交接時間長,交接質量不好,文檔缺失,很多信息在交接過程中丟失,運營事故往往頻發。
經驗難以得到傳承,一塊石頭反復絆倒各個成員和業務模塊,運營事故雷同、頻出,團隊挫折感倍增、服務可用性低下。
也曾經有過做事比較規范的時候,但是這些規范通常靠耳提面命、人口相傳,靠管理者運動式的整頓,有時候管理焦點沒有持續跟進,或者隨著人員更替,團隊又把這些寶貴的經驗丟棄了,變得無序。
所以服務標準化是后臺技術團隊組建開始的第一要務。
兩個誤區
**誤區一:**找幾個開源的組件用起來就好了唄。
- 通常的開源的組件,只是在某一方面上規范了服務,有的是規范了網絡調用,有的是規范了如何監控,有的是規范了如何記錄遠程記錄,其實這還遠遠不夠,例如配置文件、接口定義、使用到的外部庫、安裝目錄的結構等非常多的細節,必須統一管理、有唯一出處。
**誤區二:**你說的我都懂,我們團隊剛起步,業務需求多,時間緊,先野蠻生長,打破條條框框,后面再規范再改。
- 一開始沒有標準化,后面當代碼和模塊都多起來了,且都處于運營狀態,再改再標準化,難度非常大,成本非常大,風險非常大;另外工欲善其事必先利其器,一開始就標準化好,其實可以讓業務跑的更快。
如何實現服務標準化?
首先,每個服務的配置都Web化、集中管理起來。
部署在哪些IP上?
業務部署的目錄都是/msec/一級業務名/二級業務名;
都包含bin etc log 等幾個目錄;
bin里面是啟停腳本、業務插件msec.so和外部庫(如果有);
etc里面是配置文件config.ini;
Log里面是本地的日志文件。
另外,程序員不能隨意打破上面的方式。例如臨時的另外搞一個自己配置文件什么的,他如果這樣做,那下次發布的時候目錄會被覆蓋,個性化的東西會被刪除掉。
后臺服務的RPC和路由管理
互聯網服務的后臺,硬件通常是由大量的廉價機器組成;軟件架構通常采取大系統小做、分而治之的思想。這就決定了業務邏輯涉及到大量的網路IO,同時單機故障、網絡局部故障是運營的常態。那么,RPC和路由管理就顯得尤其重要了。毫秒服務引擎為此提供了一個完整的解決方案。
RPC的概念其實出現已經很久了,記得筆者讀大學的時候,接觸到RPC的概念,總覺得不重要,多此一舉。 我掌握好Socket通信這個利器和TCP/IP協議族原理,什么功能不能實現?
RPC就跟本地函數調用一樣寫代碼,確實開發效率比較高;我自己把Socket相關函數好好封裝一下,讓代碼復用起來,開發效率也很高。
不懂或者不關注網絡通信底層原理,光會函數調來調去,這樣的程序員太沒有出息了!
后來,筆者開始帶團隊,親身經歷了一些團隊協作和IT服務運營過程中的故事,才發現RPC非常關鍵。如果沒有很好的實現RPC和路由管理,IT系統服務質量會過度的依賴人的意識,而這個通常成本非常高、效果也不好。
毫秒服務引擎是怎么做的?
首先,毫秒服務引擎將每個服務部署在哪些IP上這些信息集中管理起來,即使是調用外部的非標準服務(我們叫異構服務),也需要將該外部服務的接口IP配置到毫秒服務引擎管理系統里。這樣涉及到的IP信息就不會散落在代碼和各種配置文件里了。
毫秒服務引擎框架本身,在RPC執行的時候,就上報了很多基礎屬性和日志,這樣保證了服務監控和告警等運營措施不依賴與人的意識。下圖是叫做getMP3List這樣一個RPC調用的請求數和成功數,這些是不需要業務開發者工作就自動上報。
后臺服務的灰度發布與監控
灰度發布和監控是互聯網海量服務必備的兩大利器,能夠極大提高后臺服務可用性和運營水平,背后的哲學是持續交付、用戶測試和盡在掌控。
在騰訊,有一個課程系列,叫做《海量服務之道》,包含十多門課程和方法論,是技術同事必修和必知必會的,其中兩門課程就是《灰度發布》和《全方位監控》。
筆者在加入騰訊QQ后臺團隊之前,曾經在電信行業、金融行業做過幾年開發工作。剛進入騰訊時,覺得技術上很多地方讓人耳目一新。
后臺系統都是部署在非常多的廉價服務器上,每個人都會管理非常多的機器,讓人覺得很有成就感很富有。
有比較精確的設備預算計算模型,每個服務器的性能在考慮容災冗余的前提下,通常被壓榨到剛剛好,負責人會深入的洞悉整個系統的性能、容災、柔性等方方面面。能負責一個海量的系統是很榮耀的一件事情。
沒有專職的測試人員,經過開發者自測后,灰度發布加詳細的監控,主要的系統幾乎每兩周都會被發布一輪,作為后臺技術人員,自己的工作直接影響數以億計的用戶,有點手握核彈處于上帝視角的感覺。
監控系統(我們內部一個叫monitor的系統)真的是太方便了,一條條曲線直觀的展示整個系統運作的各種指標,如果有異常短信和電話就會響起來,讓人覺得一切盡在掌控,有一種面對著大量儀表盤操控著航母游弋或者是戰斗機掛著核彈翱翔的感覺。
好了,趕緊結束程序員意淫的美好感覺,我想說的重點是:灰度發布和監控真的是互聯網海量服務必備的兩大利器,能夠極大的提高后臺服務可用性和運營水平。
當然,灰度發布不只是一部分一部分的發布新代碼,監控也不只是繪制曲線和告警短信那么簡單,這里面深究下去會有很多東西,背后的哲學是持續交付、用戶測試和盡在掌控。
毫秒服務引擎是怎么做的?
#####灰度發布 在服務配置管理頁點擊“制定發布計劃”。
監控
關于監控,在“RPC和路由管理”那里講得已經比較詳細了,這里不贅述。只說明一下:除了RPC和框架本身自動上報的一些信息,還支持業務自定義上報信息(例如我想上報第28級VIP用戶登錄的次數),且支持對于關鍵指標的波動、最大值、最小值設置告警。
KV存儲集群的設計要點
Key-Value存儲系統,是非常普遍的需求,幾乎每個在線的互聯網后臺服務都需要KV存儲,我們團隊在KV存儲方面,經歷過幾個時期,我自己深感要做好不容易。
第一個時期,很早期的時候,我們的數據存儲在MySQL表里,按照用戶賬號簡單的分庫分表,為了保證訪問高并發,利用每個MySQL服務器的內存做數據緩存;主備兩套分布在不同IDC,業務邏輯自己做副本同步。當時主要的問題是:內存的數據結構擴展困難、運維工作瑣碎、數據同步機制本身的缺陷導致不能做異地IDC部署,這些缺點對于業務飛速發展、一地機房已經不夠用的局面非常被動。
第二個時期,我們設計了新的KV存儲系統,其用戶數據結構容易擴展、具備可以多地部署的數據同步機制,很好的應對了新時期業務發展的需要。為了設備成本考慮,我們把數據做冷熱分離,訪問頻繁的數據會加載到專門的Cache層,且對于不同的訪問模型,掛載不同架構的Cache,另外一個File層專門做數據持久化。這樣的設計,使得架構太復雜,bug收斂速度慢,運維工作相比以前甚至更復雜了。
第三個時期,為了應對普遍的KV存儲需求,我們以公共組件的形式重新設計了KV存儲,作為團隊標準的組件之一,得到了大規模的應用。結合同期抽象出來的邏輯層框架、路由管理等其他組件,團隊的公共基礎組件和運維設施建設的比較完備了,整個業務的開發和運維實現了標準化。但這個階段就用了我們團隊足足2年多時間。
不同于無數據的邏輯層框架,KV存儲系統的架構設計會更復雜、運維工作更繁瑣、運營過程中可能出現的狀況更多、bug收斂時間會更長。一句話:團隊自己做一個KV存儲系統是成本很高的,而且也有比較高的技術門檻。
設計一個KV存儲,需要考慮至少這些方面。
如何組織機器的存儲介質,通常是內存、磁盤文件;例如用hash的方式組織內存。
如何設計用戶的數據結構,使得通用、易于擴展、存儲利用率高;例如PB序列化、Json、XML方式。
友好的訪問接口,而不只是get/set一整個value。
如何做集群分布、如何sharding、如何做到方便的擴縮容;例如一致性hash算法。
如何做數據冗余、副本間如何同步、一致性問題;副本間如何選舉master。
備份與恢復、數據校驗與容錯。
讀寫性能。
其他可能的特殊需求:例如我們設計過一個KV存儲,用于存儲一些公眾號的個數不受限粉絲列表。
上面8點,業內的KV存儲組件一般都會考慮到,或者各有特色,各自優勢在伯仲之間。但是綜合過去的經驗教訓,我們覺得有一點很容易被忽視:可運維性、運維自動化、黑盒化運維。
舉一個例子,前面提到的我們第二個時期的KV存儲系統,剛開始應用的時候,一次擴容過程會有10多步的運維操作,包括load數據、做增量同步、多次修改機器狀態、數據比對等等,需要運維同事以高度的責任心來完成。另外就是運維同事必須如該KV存儲架構設計者一樣深刻理解系統背后的原理和細節,否則就不能很好的執行運維操作,這個要求也非常高,新老交接周期長,還容易出運維事故。
基于上面的考慮,同事為了讓用戶更容易學習和接受,毫秒服務引擎在Redis Cluster的基礎上,實現了運維Web化,并加上了集群的監控。
通過Web界面方便進行
集群概要狀態查看。