荔枝架構實踐與演進歷程

雲端計算頻道發表於2019-01-23

黃全,荔枝APP架構師。擁有10年的網際網路開發經驗,對分散式系統、高併發解決方案有著豐富的實踐經驗,在國內知名網際網路企業擔任過資深工程師、系統架構師等職。曾就職於UC瀏覽器、春筍新科技。現任荔枝資深工程師,負責基礎架構的設計與開發,目前專注於分散式系統、微服務、資料庫中介軟體等技術的研究與探索。2018年10月18日,黃全 受邀參加了由IT168主辦的《SACC 2018第十屆系統架構師大會》,並發表了精彩演講,以下內容根據 SACC大會實錄整理。

如果你對聲音互動平臺有所瞭解,那對於荔枝APP一定不會感到陌生!

荔枝,致力於打造聲音處理平臺,幫助人們展現自己的聲音才華。荔枝集錄制、編輯、儲存、收聽、分享於一體,依託聲音底層技術積澱,具有聲音節目錄制功能,可在手機內完成錄音、剪輯、音訊上傳和語音直播。

簡單理解,荔枝APP上有很多主播,主播和使用者之間可以透過聲音互動。目前,荔枝APP月均活躍使用者達到好幾千萬,月均活躍主播達到好幾百萬,全球註冊使用者和音訊節目數量都已過億。

那麼,對於有著大使用者量的社交APP來說,荔枝APP的背後架構該如何設計?一個時間軸可以概括整個架構的演進過程。

架構演進時間軸

  • 2013年:單體架構。

這個時候的架構是V1.0版,主要特點是APP 直連伺服器,服務端是單體架構。也就是說,一個服務,一個儲存解決所有問題。這種架構看上去簡單、粗暴,好處是快速上線、快速響應市場需求;但劣勢也非常明顯,APP直連伺服器模式在擴充套件的時候非常不靈活。專案上線後3個月,使用者數突破 100萬,訪問量上漲,伺服器壓力增大。

  • 2014年:垂直架構

到了2014年,荔枝APP的後臺架構演進到V2.0版。這一版架構的特點是:支援水平擴充套件和功能拆分。首先,APP 與 app server 之間加入app代理層,用於分發請求給多臺 app server,分攤壓力。其次,對app server 按功能進行拆分,資料操作及業務邏輯部分由後端服務負責,並採用 netty(http) + json 方式進行互動。

雖然,這個時候已經能做到相對快速互動,但是依然存在很多問題。一個是,後端服務水平擴充套件時,不能動態化;另外,系統間採用 http 互動時,通訊效率較低,並且資料包較大;還有一個問題是,json 解析速度較慢、體積較大。所以,V3.0版採取了一系列措施,重點解決擴充套件、互動等問題。比如:引入Linux虛擬伺服器叢集系統 LVS,採用 TCP 取代 HTTP,透過定製私有協議取代json。

V3.0版使用 LVS 叢集解決了分發請求,但是隨著業務的快速發展,人力資源都投入在業務開發上,對第三方產品瞭解也不夠深入,導致運維成了最大挑戰。所以,後期考慮採用自己開發代理服務來取代 LVS。

V4.0版架構中,我們開發了代理服務,當時使用 VIP 與其他服務連線,取代LVS分發請求。這時候的整體架構依然比較簡單,app server 與後端服務還是單體架構,沒有做業務拆分,雖然能讓後端服務支援水平擴充套件功能,但需要重啟代理服務。另外,還有一個挑戰是,隨著使用者量、訪問量的持續上漲,系統訪問壓力依然很大。接下來的目標是,app server 與後端服務需要按業務垂直拆分。

演化到V5.0版架構的時候,所有服務已經能夠按業務拆分,可支援水平擴充套件,整體架構能抗得住一定的訪問壓力。2014年10月,使用者量曾突破 1千萬。但新的問題又來了:一個是服務的配置不能做到熱更;另外,不同業務的後端服務之間產生了互動需求。還有,微服務化已成為主流發展方向。所以,下一個階段的解決方案是,開發配置中心 config server實現配置熱更;採用開發分散式服務框架 lz-RPC,封裝遠端呼叫功能。

  • 2015年:分散式架構

V6.0版架構開啟了分散式架構新徵程,這時候的特點是app server、後端服務、代理層等,都實現了配置熱更,能靈活水平擴充套件。到2015年9月,使用者量曾突破 5千萬。但是面臨的問題依然很多。比如:mysql、redis 操作的重複程式碼太多;mysql、redis 慢操作不能及時報警;各個服務的資料來源配置分散,難以管理等。另外,還涉及跨機房資料操作和資料同步問題。而分散式資料庫中介軟體可以很好地解決這些問題。

  • 2016年:分散式資料庫中介軟體

從2016年開始,荔枝APP的後臺架構走入V7.0版時代。這時,開發團隊自研了分散式資料庫中介軟體data store服務。data store的特點是:簡單易用,可減少重複程式碼。只需要在類上加上註解,就可以實現與資料庫的互動、資料轉換等功能,大大減少了開發的工作量。另外,data store具有自動維護快取和資料庫表的對應關係、自動維護快取與資料庫資料的一致性的功能。最重要的是,遮蔽了服務對資料來源的管理,便於資料庫的遷移和擴容等操作。

總體來看,V7.0版的最大特點是,已形成一個比較完整的分散式架構。data store 封裝了常見的 mysql、redis 操作,能提供慢操作監控。後期根據業務發展,還引入了 kafka、mongoDB、zookeeper、hbase等多種第三方產品。

隨著應用的增加,V7.0版架構也逐漸暴露出了一些缺陷。一是資源監控、業務監控、分散式跟蹤鏈等功能不完善。另外,隨著訪問量上漲,分散式服務框架的功能也需要進行擴充套件。

  • ‍‍2017-2018年:監控體系

進入2017年以後,整個架構已趨於完善,重點引入第三方產品,建立監控體系,完善對伺服器資源、業務、跟蹤鏈路等的監控,同時也擴充套件了分散式服務框架功能。也是從這個時候開始,整個架構迎來了V8.0版。經過完善後,業務監控及基礎監控功能已比較完整,分散式服務框架擴充套件了介面快取、熔斷、降級、過載保護等功能。

近兩年踩過的“坑”以及應對措施

1、大主播開直播,訪問量爆漲,影響了其他直播間的直播效果,比如出現卡頓、進入不了直播間、介面超時。舉個例子:李易峰晚上8點在荔枝APP上做直播,那麼從8點前開始,整個系統的訪問量就會比平時要高出很多。有使用者就會出現進入直播間慢、評論出現慢以及其他體驗不好的情況出現。像這樣的問題,應該如何解決呢?

第一個方案,也是最簡單的方法,是“隔離”。在 data store 中,針對 redis 儲存開發,按字首分片的功能,對大主播的直播資料進行隔離,避免影響其他主播的直播效果。

第二個方案是,在高訪問量期間,結合分散式服務框架中開發的熔斷、降級、過載保護等功能,採取對部分非關鍵服務做降級措施,避免伺服器因訪問量過高發生雪崩。

2、在高併發環境下,Mysql 查詢效能成為瓶頸。當資料量呈現爆發式增長,Mysql 查詢速度變慢。我們對分散式資料庫中介軟體作了擴充套件,在操作mysql時,在資料庫上層加入快取memcached後,大大提高了查詢效能,並且自動維護快取和資料庫資料的一致性。

3、訪問量上漲,受日誌檔案的IO影響,服務出現長GC(stop the world,阻塞業務執行緒)。類似服務出現長GC的問題,很多網際網路公司都會遇到。在GC的整個回收過程中,會有兩個步驟涉及到IO操作。第一個操作就是寫 perf 檔案;第二個是寫 gc log的時候。一臺伺服器一般會部署多個服務,這些服務在執行的過程中,會不斷輸出日誌,這時容易出現與其他服務的GC執行緒發生搶佔IO資源的衝突,而導致GC執行緒阻塞等待,最終導致整個GC過程耗時較長,影響了服務的響應和穩定。為了解決這些問題,採取了兩個方案來解決:第一,不生成 perf 檔案,在服務啟動指令碼里,加上引數 -XX:+PerfDisableSharedMem就可以了;第二,將 GC日誌儲存到記憶體盤中( tmpfs 或 ramfs ),在服務啟動指令碼里加上 -Xloggc:/dev/shm/lz-app-gc.log引數就可以解決了。

4、隨著業務的發展,系統的整體訪問量越來越大,後端服務介面呼叫耗時越來越長,導致經常超時。經過分析和統計發現,整個平臺實際上以“讀多寫少”的場景居多。有沒有一個兼顧全域性的解決方案呢?在分散式服務框架中開發“快取介面”功能,解決了這個問題。其實有很多場景,我們是不需要實時看到最新資料的,即使新資料晚了30秒或者1分鐘使用者才看到,也是可以接受的。

5、系統間非同步訊息通知功能不完善。之前,是透過redis來做非同步訊息通知,好處是比較輕量化,但是隨著資料量增加,大資料傳輸增多,出現多個消費方需要消費相同訊息的時候,redis 就不是很適用了。這時,使用 kafka可以滿足系統間訊息通知、大資料量傳輸、多個消費者消費相同訊息的場景。

6、當服務框架中的各種功能都比較完善後,卻發現缺少一個報警功能。比如在請求失敗/超時/異常等,如果有監控機制,就可以找到具體的問題點。藉助監控系統,我們可以看到伺服器負載、實體記憶體、swap、磁碟等資訊,也能監控到GC資訊的回收時間、次數以及JVM堆資訊等,還可以對異常請求進行統計。

7、隨著服務的增多,每個服務都有很多例項,導致整個架構的呼叫鏈路不清晰,也不能預知整體架構存在的瓶頸。引入skywalking 實現呼叫鏈跟蹤功能後,能快速定位到線上故障和整個架構的效能瓶頸。

8、主要是更新服務的問題,上線/重啟服務操作很原始,之前都是人工在本地打包,再上傳到伺服器。服務不多的時候還能支撐,但是服務例項數量開始增多的情況下,這種方式就需要改進。荔枝的做法是開發一個自動釋出平臺,一鍵式操作。另外,就是透過jenkins + gitlab,接入自動釋出平臺,實現自動打包、一鍵釋出。

9、服務釋出流程不夠規範。過去的部署流程很簡單,先是在本地測試,測試透過後,打包部署到線上,再觀察服務的執行日誌。但是隨著團隊人員和系統越來越多後,這種做法是不合適的。要想保證整個業務順利上線,必須把服務釋出流程規範化。從預釋出測試到影響評估,到回滾步驟,再到灰度釋出、線上驗證,每一個環節都要標準化。預釋出測試包含業務流程測試、新功能測試、SQL 驗證、程式碼審查;影響評估包含對業務系統的影響和對互動系統的影響;回滾方案包含回滾步驟和回滾版本號,灰度釋出則要按照按流量百分比、按裝置型別和按 app 版本號等來操作;線上驗證要做功能迴歸測試,以及觀察異常日誌、報警資訊等。

10、研發規範不夠標準。一個技術團隊從10幾個人發展到幾百人甚至上千人的時候,規範很重要。為了提高效率,公司制定了各種標準的開發/操作規範,包括客戶端開發規範、服務端開發規範、測試規範、運維規範、mysql、redis、kafka、mongoDB 等的使用規範。

未來對整個架構會有多個最佳化的目標,例如透過“微服務+容器化”實現服務例項的動態擴容與縮容、Service Mesh架構改造、業務級別的呼叫鏈跟蹤功能等等。

最後,引用大家常說的一句話:好的系統不是設計出來的,而是演進出來的。未來,荔枝的系統架構會更加完善,在不斷探索中更加精進。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31545808/viewspace-2564510/,如需轉載,請註明出處,否則將追究法律責任。

相關文章