內容來源:之前作者寫了一篇《FunData — 電競大資料系統架構演進》的文章,傳送門:http://t.cn/RdgKWGW 覺得沒有深入寫出一些深層次的東西。糾結了幾個晚上決定重寫一篇不一樣的文章。本文由IT大咖說(微信id:itdakashuo)整理,經投稿者與嘉賓審閱授權釋出。
閱讀字數:3497 | 9分鐘閱讀
摘要
本文與上一篇完全不同,從另一個角度來闡述為什麼FunData的系統需要優化,整理出怎麼優化架構的一些思路吧,希望能為各位看官帶來一些靈感和思考。
我們還是先從FunData的兩張架構圖開始吧。
圖1 ETL 架構圖1.0
圖2 ETL總架構圖2.0
架構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的合理分配和高可用;儲存層使用儲存代理,負責讀寫分離,批量寫入及資料聚合等工作。
像日誌服務、監控服務和底層的應用管理平臺、雲平臺作為任何形態的系統都必不可少的模組,服務於整個系統。
FunData監控
FunData日誌分析
除了使用旁路系統為整個系統保駕護航,程式碼層面上也有不少工作,比如為提升內部系統通訊的成功率和穩定性,我們需要增加重試的機制;對於內部使用的佇列、物件儲存和註冊服務等封裝了統一的SDK,提供連線池、定時更新服務列表及註冊搶主等機制。
到目前為止,微服務架構已經被不斷的實踐,圍繞微服務架構的技術棧也層出不窮,例如Spring Cloud系列的微服務框架(如下圖),傳統的ELK日誌服務,Prometheus/Falcon監控系統,Etcd分散式儲存,kubernetes容器服務等。
然而,微服務的架構不是萬能的,隨著系統的增多,對系統的管理成本會逐漸增加,服務之間的依賴關係也更加複雜。對於一個大型微服務系統(上百個節點的那種),工程師需要花大量時間去理解裡面的呼叫依賴。另外一點也是我的切身體會,在開發業務邏輯時,對於上述提到的重試機制、智慧RPC排程及限速限流等功能,有時並不是我最關心的,業務邏輯才是核心,但是在微服務架構中不得不注入更多的保護程式碼,或者引用個龐大的通用SDK來完成這些功能。為此,2017年左右,業界提出了Service Mesh的概念。
借大佬的話“Service Mesh通常用於描述構成這些應用程式的微服務網路以及它們之間的互動。隨著規模和複雜性的增長,服務網格越來越難以理解和管理。它的需求包括服務發現、負載均衡、故障恢復、指標收集和監控以及通常更加複雜的運維需求,例如A/B測試、金絲雀釋出、限流、訪問控制和端到端認證等”。
https://www.nginx.com/blog/what-is-a-service-mesh/
Service Mesh不是一個新的架構體系,而是作為微服務架構的一次升級,將服務發現、負載均衡、故障恢復等在架構設計中系統層面的優化抽象出來,作為一層基礎設施,用於搭載各個業務邏輯。高大上的說法就是,讓演算法專注於演算法,業務服務於業務。通過Service Mesh將系統Robust的各中優化與保護脫離於業務開發,可能未來就是系統工程師和業務開發工程師的區別了。
Serverless
最後的最後,Serverless的架構也是大家可以考慮和選擇的。我們在內部也有Serverless系統的實踐。
《Serverless的概念與系統架構設計》傳送門:https://myslide.cn/slides/8295
在考慮serverless架構時,主要有以下幾個考量
成本 - Serverless作為更碎片化的一種架構模式,這類服務一般只對使用多少核小時進行計費,不需要關心伺服器部署
耗時計算或流量不穩定的計算 - Serverless系統一般搭載大量機器提供10萬級以上的核數,如果業務上有一些演算法消耗計算時間或者存在大量併發的突發情況,可以考慮將業務邏輯和演算法接入Serverless做處理,減少運維壓力。
事件觸發的Pipeline - 舉個例子,我們會把圖片、視訊等靜態資源上傳到物件儲存, 單張圖片可能就有多種使用場景,例如需要裁剪、轉格式或者增強之類,這時可以使用Serverless服務,即在有圖片上傳時觸發各種圖片處理的演算法。
傳送門關閉~~~搓爐石回城