架構的一些思考From FunData
來自專欄 VPGAME/VPESPORTS的北美黑科技作坊8 人贊了文章
瀉藥在VP黑科技作坊寫篇關於電競大數據的文章。之前想的是直接用CSDN上發表的那篇投稿好了。
傳送門
一文了解電競遊戲平台的大數據玩法兒! - CSDN博客但是作者糾結了幾個晚上決定還是重新寫一篇不一樣的文章,從另一個角度來闡述為什麼FunData的系統需要優化,整理出怎麼優化架構的一些思路吧,希望能為各位看官帶來一些靈感和思考。
我們先從FunData的兩張架構圖開始吧。
架構1.0和2.0都屬於微服務架構,架構2.0在原有的基礎上對數據傳輸的模型,數據存儲與渲染的方式及服務治理等方面做了更多的改進。
- 數據傳輸模型
1.0架構我們選擇的主語言是Python,系統模型是Master-Slave,通過Python自帶的MQ庫構建數據傳輸的模型。處理的邏輯即從STEAM公開介面拉取比賽數據,將比賽任務分配給各個Slave節點處理,處理記錄元數據和處理的數據落地MySQL。
InMemory的隊列模式,對我們系統維護上帶來許多不方便。Slave節點的更新重啟,因為沒有註冊服務保證任務執行完後節點的正常下線,重啟時很隨機,無法保證在節點內的任務正常執行完;Master的節點更新重啟,需要所有Slave節點全部重啟一次,建立新連接,當然這裡可以用重連機制(這個之後會結合service mesh討論)。
因此架構2.0使用MQ服務將上下游的系統解耦開,並採用消息匯流排的方式推送消息,從原來的Master-Slave的方式轉成Controller-Worker的方式,這樣的好處是一方面系統更新沒有依賴,亦不需要重啟整個系統;另一方面,更加細化的worker可以讓我們的針對不同數據要求編寫worker,使得數據處理變得更可控(可插拔的方式),有針對性的做worker擴容,資源使用率更加精準。
- 數據落地方式
早期我們使用的是主備模式的MySQL,容量上限為2T,存儲上很容易出現瓶頸,當時沒有分散式MySQL和讀寫分離模式,達到容量瓶頸後,只能新增一個主備MySQL,在ETL和API層多配置一個DB入口做數據存儲和聚合處理,著實很麻煩,另外配置要維護的很準確;另外團隊數據點的需求一直在變化,結構化的存儲很不利於數據點的擴展。
2.0里我們果斷選擇NoSQL且分散式存儲的方式,具體請參考FunData電競大數據系統里對數據存儲的設計和思考吧。
- 服務治理
1.0的系統屬於快速迭代上線的產物,旁路系統的建設幾乎為0,系統在線上常常是「裸奔」的狀態。為了保證服務的穩定性,我們引入了很多旁路建設。
K8S - 減少服務運維壓力,增加系統的擴展性。
日誌系統 - 系統處理異常可追蹤
灰度系統與負載均衡 - 介面更新及請求流量可控
Harbor + Registry - 鏡像倉庫統一管理,代碼分版本
CI/CD - 快速上線,統一部署與測試
Serverless - 將耗資源的演算法,分配到serverless服務,不獨立維護系統,pay-as-you-go
...
我們在FunData的微服務架構上還在持續優化,通過更好的架構和計算模型處理更多的數據,處理更多的電競遊戲數據。
看了FunData的架構優化後,可能大家有疑問說我們在系統的架構設計上為什麼不能一步到位呢?微服務架構是"萬金油"么?
個人認為系統設計是沒有統一公式的,關鍵在於在系統迭代的過程中,通過合理的分層與組合得到符合業務發展的架構形態。在系統架構設計上有如下一些思路,供大家參考。
單點系統
項目早期或者demo階段,單點服務設計的方式會更加適合。一方面快速驗證想法,另一方面沒有太多成本上的壓力,不要考慮HA/AZ容災之類,功能實現和業務邏輯的自證才是核心。
對於小團隊,單點服務使用一個repo維護代碼已經足夠,也只需要一台伺服器跑起服務即可。
微服務
微服務架構的使用,可以從以下幾點考慮
- 團隊變大,單個repo的代碼變得臃腫,包含10幾種的業務功能,比如商城的登錄、用戶體系、購物車、支付等等。這種一個panic就搞垮整個商城的設計已經無法滿足業務發展。
- 資源使用率參差不齊,可以考慮把邏輯拆分出來,對更細化的系統做合理的擴展,也不容易遇到一個業務瓶頸拖垮整個網站的情況。
- 系統需要分層和抽象時,比如拆分部分邏輯後,再整個系統需要一個統一的接入層做請求的調度,再比如數據量增大時,需要有獨立的數據代理層來處理數據的聚合和batch insert的操作。
設計微服務架構時,一般是分層的設計思路,主邏輯鏈路上一般可以分為接入層、邏輯層、存儲層,各旁路系統則是服務於各個主鏈路層的各種服務。
例如:接入層引入負載均衡和灰度系統,實現流量控制,限速限流,高峰降級等;邏輯層接入註冊服務和調度服務,幫助處理內部RPC的合理分配和高可用;存儲層使用存儲代理,負責讀寫分離,批量寫入及數據聚合等工作。
像日誌服務、監控服務和底層的應用管理平台、雲平台作為任何形態的系統都必不可少的模塊,服務於整個系統。
除了使用旁路系統為整個系統保駕護航,代碼層面上也有不少工作,比如為提升內部系統通信的成功率和穩定性,我們需要增加重試的機制;對於內部使用的隊列、對象存儲和註冊服務等封裝了統一的SDK,提供連接池、定時更新服務列表及註冊搶主等機制。
到目前為止,微服務架構已經被不斷的實踐,圍繞微服務架構的技術棧也層出不窮,例如Spring Cloud系列的微服務框架(如下圖),傳統的ELK日誌服務,Prometheus/Falcon監控系統,Etcd分散式存儲,kubernetes容器服務等。
然而,微服務的架構不是萬能的,隨著系統的增多,對系統的管理成本會逐漸增加,服務之間的依賴關係也更加複雜。對於一個大型微服務系統(上百個節點的那種),工程師需要花大量時間去理解裡面的調用依賴。另外一點也是我的切身體會,在開發業務邏輯時,對於上述提到的重試機制、智能RPC調度及限速限流等功能,有時並不是我最關心的,業務邏輯才是核心,但是在微服務架構中不得不注入更多的保護代碼,或者引用個龐大的通用SDK來完成這些功能。為此,2017年左右,業界提出了Service Mesh的概念。
借大佬的話「Service Mesh通常用於描述構成這些應用程序的微服務網路以及它們之間的交互。隨著規模和複雜性的增長,服務網格越來越難以理解和管理。它的需求包括服務發現、負載均衡、故障恢復、指標收集和監控以及通常更加複雜的運維需求,例如A/B測試、金絲雀發布、限流、訪問控制和端到端認證等」。
傳送門
What Is a Service Mesh? - NGINXService Mesh不是一個新的架構體系,而是作為微服務架構的一次升級,將服務發現、負載均衡、故障恢復等在架構設計中系統層面的優化抽象出來,作為一層基礎設施,用於搭載各個業務邏輯。高大上的說法就是,讓演算法專註於演算法,業務服務於業務。通過Service Mesh將系統Robust的各中優化與保護脫離於業務開發,可能未來就是系統工程師和業務開發工程師的區別了。
Serverless
最後的最後,Serverless的架構也是大家可以考慮和選擇的。我們在內部也有Serverless系統的實踐。
Serverless的概念與系統架構設計傳送門
俞圓圓 - 電競數據的容器實踐 — serverless的電競數據計算平台在考慮serverless架構時,主要有以下幾個考量
- 成本 - Serverless作為更碎片化的一種架構模式,這類服務一般只對使用多少核小時進行計費,不需要關心伺服器部署
- 耗時計算或流量不穩定的計算 - Serverless系統一般搭載大量機器提供10萬級以上的核數,如果業務上有一些演算法消耗計算時間或者存在大量並發的突發情況,可以考慮將業務邏輯和演算法接入Serverless做處理,減少運維壓力
- 事件觸發的Pipeline - 舉個栗子,我們會把圖片、視頻等靜態資源上傳到對象存儲, 單張圖片可能就有多種使用場景,例如需要裁剪、轉格式或者增強之類,這時可以使用Serverless服務,即在有圖片上傳時觸發各種圖片處理的演算法。
傳送門關閉~
推薦閱讀:
※綠城關鍵時刻:內部架構大調整 輕重並舉啟動高周轉
※架構控制的從權問題
※分散式架構與微服務架構——成為高級架構師,你想要的都在這裡
※58架構師解讀:如何優化秒殺業務的架構?
※《App架構師實踐指南》