以前章魚保羅做的預測,現在有企業專門在做了~

2010 年南非世界盃,「預言帝」章魚保羅搶走了原本屬於球星的風頭,它精準的預測了德國國家隊的比賽結果;現實中,我們每個人也會對比賽結果進行娛樂性的預測,關注自己喜歡的球隊,而有這麼一家專業的公司,卻利用着大數據、人工智能、神經算法來給體育比賽結果預測,對體育進行服務 —— 智慧摩羯數據科技有限公司。

智慧摩羯數據科技有限公司,是一家專注於體育運動大數據分析服務的創新型科技公司,以賽事數據爲基礎,以大數據分析爲引擎,運用機器學習、深度學習等人工智能算法來實現全球體育比賽結果預測、體育運動指導、電子競技遊戲支持等服務。

智慧摩羯數據科技有限公司聯合創始人陳健,分享瞭如何解決隨着業務發展,系統越來越臃腫、應用變得越來越不易維護、不易擴展等問題,並分享智慧摩羯在搭建企業微服務中的相關經驗。以下爲演講正文:

大數據分析技術是企業的核心競爭力。主要的技術分爲兩部分:

  • 第一部分是大數據技術;
  • 第二部分是應用的技術,即大數據服務和應用服務。

img

大數據服務跟絕大多數公司差不多,首先是數據採集,我們有很多爬蟲,可以直接在公網爬取全網數據,爬取到全網的體育數據後,我們對數據進行分析,然後就是數據處理和建模。早期我們通過大數據分析技術把這些數據跑出來,進行建模,進行結果預測。現在我們開始進行一些更深入地研究,像機器學習、深度學習,還有神經網絡等相關算法都已經引進並運用。希望通過這些人工智能算法更智能、更科學地預測一場比賽,或者對體育進行服務。

img

正是基於核心技術,智慧摩羯佈局了三條產品線:

一是體育比賽預測,就是剛跟大家分享的,通過去全網扒數據,運用人工智能算法分析進而預測體育比賽結果。

二是體育運動指導,通過收集所有運動員及體育愛好者的運動數據,對其進行專業地指導。

三是電競遊戲支持,我們發現電競其實也可以進行各種各樣的數據收集、分析和預測,智慧摩羯可以爲電子競技類遊戲提供專業的數據支持,讓遊戲更加專業、真實和有趣。

技術架構

第一部分是技術的演化過程,主要講種子期和成長期。

img

早期是把代碼放在 GitHub 上,爲了把業務拆得足夠細,所以創建了很多代碼庫,但智慧摩羯當時只有一兩個後臺工程師,很快就拆出超過 10 個庫。這樣維護起來成本太高,代碼重複,且沒有精力合到公共的代碼庫裏,我們發現這條路走不通。

img

這就是智慧摩羯早期的架構,特點是代碼庫特別多,我們有前端負載均衡,有 API 服務,有消息隊列服務,定時任務服務,這時候 Redis 是單節點的,MySQL 也是單節點的,是很簡單的架構。實際上代碼庫多對我們來講是比較重的事情,然後我們就把多個代碼庫合成一個,解決公共庫的問題,代碼的冗餘度降低了。雖然單個數據庫根據業務劃分多個 schema,但是還是在一個數據庫裏面,然後單個 Redis 節點,存放所有的緩存數據,這樣也可以降低成本。

img

問題就是單體工程越來越龐大,一年我們就做了幾十萬行代碼的量級,還是一個工程代碼庫。還有一個特點就是文檔少,重複代碼多。由於開發人員增加了,從兩三個人變成了十幾個人,導致重複代碼越來越多,因爲不是每個人都對代碼理解,文檔少,必然就會理解少,重複的代碼多。數據庫無法根據業務分攤壓力,單失效節點多,事故也頻繁出現。

img

這是智慧摩羯這時簡單的架構圖,GitHub 是單一的節點庫,增加了很多運維腳本,當時 VM 在 QingCloud 上就有幾十臺。

微服務解決方案

img

沒有問題就沒有動力去改變這個事情,所以我們先來看下有哪些問題。

第一個特點是單個節點的數據庫承受所有的應用層壓力,*沒有進行拆分。*這時候數據庫其實是最大的瓶頸,一旦它發生阻塞,整個服務就癱瘓了。因爲所有的連接一直在那兒阻塞,沒辦法接新的連接,整個服務就是完全阻塞的狀態。

第二個特點,單個 Redis 承受所有的緩存的數據,服務癱瘓,恢復時間慢。單體工程代碼量非常龐大,新人頭疼,無從下手。開發人員變多,出現的事故概率增大,系統升級的風險變高。

代碼的衝突也頻繁發生,這時由於每個人不太瞭解,合併的時候頻繁出現代碼被覆蓋的情況,我們的開發分支跟線上穩定分支總會出現各種各樣的問題,升級的風險非常高。應用層都部署在 VM 上,上百節點的 VM 沒有分開,這是我們的問題。

img

針對以上問題,兩個核心的解決方案:第一個是隔離,第二個是解耦。一部分是靜態的部分,就是代碼的部分。然後動態的部分就是運維,如果不談運維、不談代碼就有點空。首先是隔離,工程代碼要隔離,然後代碼跟代碼之間不要互相干擾。第二個是運維事故要隔離。然後是解耦,代碼要解耦,系統升級要解耦。

img

一個目標就是要放權,我對微服務的理解就是產生很多的子服務以後,首先你的代碼庫拆掉,之前代碼庫的管理權限是給到整個研發部,很多事情需要統一的授權。但是代碼庫拆掉後你就可以把權力下放到各個業務小組,由他們來決定代碼的合併和代碼的系統升級,這樣的話就等於把這個權力下發下去了。整個微服務實施的步驟是數據庫的 schema 拆分,接口流量拆分,微服務的註冊發現,管理服務的生命週期。

img

首先是代碼庫,我們先把 GitHub 的代碼庫由一個工程 fork 出來很多子工程,其實都是一樣的,因爲短時間內如果想以最快的速度把工程拆掉,這是最簡單的辦法。

img

這是第一點,然後把一些公共的合起來,剩下的全部拆掉。拆掉的過程中肯定會有一些跟這個業務不相關的代碼,但是至少保證了每一個工程可以獨立的進行分支合併。

img

第二點是我們的數據庫進行了比較大的改動,原來可能是單個數據庫,就只有多 schema 的架構,現在我們把原來的數據庫拆成八個,這些都是做事務的數據庫,然後用 MariaDB,因爲 MariaDB 支持多元複製,把這些子數據庫,這些不同的 schema 合到一個數據庫裏面,這樣可以把數據庫分開。

另外就是分表的問題,我們通過阿里開源的 Otter 來解決,實際上是僞裝成了一個 MySQL 的 Slave,不停地從 Master 裏面同步數據。然後可以建立多張表跟一張表的映射關係,建立完畢以後把多張表合成一張,這樣我們有分有合,用戶查的是分表數據,但是我們後臺統計的是合表數據,合表數據可以提供給管理後臺的人員用,給做運營、做分析的人用,這樣也能把數據庫壓力分散掉,線上就是線上,我們自己後臺的分析就是後臺的分析,把 OLTP 和 OLAP 分離。

img

我們規範了合併流程,原來只有兩個分支,一個是 Master 分支,一個是 Develop 分支。相信大家比較瞭解,Develop 分支就是開發分支,主要開發新的 features,比如說我們要開發新版本,所有的 features 開發完畢以後,就會進入集成測試的分支。但是開發人員在測試階段還可以改代碼,這個事情如果沒有規範好,會導致測試人員做很多無用功。最後我們覺得需要給測試人員足夠的權限,他們來管理一個單獨的分支。

這樣的話所有的開發人員往這個分支合併代碼的時候必須經過測試人員的同意,測試再去測這個獨立分支的時候,如果測完沒有問題,再往 Master 合併,能保證測的代碼就是要升級的代碼。同時爲了保證流程,如果線上發現了一個 bug,應該以 M 打頭,通過它 fork 出來一個子分支,然後往三個分支同時進行合併,依次合併。這個代碼的分支合併的規範流程,其實對我們來講還是很重要的。這裏面解決了很多開發人員不規範,亂提交代碼的問題。這個很有用,能保證代碼的質量。

接着我們對線上所有的服務進行拆分,拆分之前我們就是一個單體服務,很麻煩。如圖:

img

最前面是負載均衡器,這個就不用說了,用的是青雲的負載均衡器。在負載均衡器後面,我們自己加了一層是 API gateway,我們把接口、定時任務、消息隊列等這些模塊按照功能爲單位,依次進行劃分,劃分成幾百個服務。

這幾百個服務沒必要每個服務一臺機器。對哪些服務需要訪問哪些資源連接進行整理歸類,比如有的是訪問用戶的數據庫,有的是訪問訂單數據庫,但是他們訪問的時候也會分讀寫,到底是讀數據還是寫數據。

然後我們再把所有的這些幾百個服務、接口,每一個都仔細過了一遍,然後把哪個該走讀,哪個該走寫,全部歸好類,把所有的配置配好,然後由 API gateway 轉到不同的機型,可能配的是讀庫或者寫庫,把線上的幾百個接口拆成幾百個服務,每一個服務能做到對其他的服務最小力度地干擾。

原來數據庫阻塞了,然後應用層組塞,整個用戶就阻塞了。現在變成了我們可以逐步降級服務,給用戶提供更穩定可靠的服務,不至於出問題。

img

這是我們用青雲的 AppCenter 2.0 做的這個事情。在去年青雲的 AppCenter 2.0 發佈會上,我覺得能夠幫助智慧摩羯實現業務。

我對它的理解就是,它在定義角色,定義生命週期。裏面包含了存儲的角色,計算的角色,包含 RDB、包含 Redis、包含 Zookeeper,可以包含很多的角色。然後這一個角色可以定義很多參數,因爲這些參數就是配置參數,原來的配置參數可能不統一,比如說 Redis有 Redis 的配置參數、Zookeeper 有 Zookeeper 的配置參數。

整體的把所有的配置參數都抽象出來,然後生命週期裏比如說服務的創建、服務的銷燬、服務的啓動、服務的關閉、服務的 Scale In&Scale Out,還有監控,健康檢查,每一個過程定義好以後,這些過程都能夠觸發我們提前定義好的腳本,這個腳本能夠在生命週期裏做它該做的工作。

然後我們把我們的服務註冊在青雲的 AppCenter 2.0 裏面,當服務啓動以後我們的服務之間怎麼訪問呢,這是依賴於我們用的 consul 的框架,每一個節點啓動以後會有一個 consul 的 Agent,Agent 用來獲取其它服務的地址,完成微服務之間的訪問。

同時服務的註冊和發現,還有健康檢查,也依賴於 consul 的 sever,例如,我要註冊一個服務,我的 IP 是什麼,我的信息是什麼,放到哪裏,其他的服務就能同步下來,並且找到這個服務。

img

下一步,原來傳統的部署是程序對接資源,資源是指的是什麼?比如說 VM,計算資源、存儲資源都算資源,我理解的是,物理設備這些東西都叫資源。

然後程序直接對接資源,這會導致我們有很多的配置文件,由於存在不同的環境,可能不同的環境只是配置文件不同,那麼這個配置文件不同就導致了多一個環境就多一套配置文件,所以需要對配置文件進行管理,配置文件發生變化以後需要對相應的服務進行更新和同步。比如說經常出現配置文件和實際部署的服務發生不一致,如果是不一致的話就會出問題。

而現在還有一個特點,當你管理幾百個節點的時候會很痛苦,它們到底是屬於哪一個服務的,你不清楚,因爲對你而言它就是一大堆幾百個節點的資源,都在青雲的管理後臺裏,只能通過標籤分類。但這並不準確,如果有人粗心把標籤打錯了,你就會誤判,而且可能只有運維人員最瞭解,其他人都不懂。

中間經過 AppCenter 2.0 以後,我們做的微服務,相當於隔一層,程序直接不去對接資源,而是對接 AppCenter 2.0 裏面的一個微服務。

這個微服務裏面定義了需要的參數,這些參數不是配置文件,而是在服務啓動的時候纔會真正有這麼一個東西,這是在微服務啓動的時候,比如說我需要一個 MySQL,它是哪一個 IP 地址,主從是什麼樣的結構,我需要一個集羣,它是什麼樣的配置參數,你在創建的時候再填寫,這樣的話由 AppCenter 2.0 去創建資源、創建服務,把這些資源提起來,並且管理服務的生命週期。

通過這些我們把幾百個節點,完全按照以服務爲角度進行歸攏和聚類,方便我們的管理。

img

接下來談談還有哪些工作我們沒有做,其實我們剛纔說的這些工作都是比較初級的,是能幫助我們的最快的手段。開發人員沒有投入太多的代碼的改動,我們就把整個服務拆掉,拆成十幾個微服務。我認爲智慧摩羯接下來要做的事情,或者說智慧摩羯還沒有完成的工作。

第一個就是認證授權,智慧摩羯的微服務之間現在雖然說是內部系統,但是互相之間也應該有一個授權操作,現在是因爲公司的業務沒有到一定的程度,到一定的程度的話是否允許互相認證訪問是應該有授權的。

還有性能監控,拆掉之後每一個服務的性能,延遲還沒有加監控。再就是流量控制,假如說某一個服務知道它大概能承受多少量級的壓力,如果這個壓力過線,我們就能自動進行熔斷,而這個還沒有做。

總結和反思

img

通過以上這些操作,我們消滅了單失效節點。MySQL 的每一個服務都有主從,可以把壓力分擔。應用層都解決了。解耦單體工程,每個微服務的代碼庫由每個小組進行維護,原來每一次升級都是一次大動作,所有的研發工程師都比較緊張,需要一起溝通交流,然後盯着升級,擔心其是否會出現問題。

現在通過這種方式避免了各個模塊之間的代碼干擾,解決了之前有可能你改了這個代碼卻引起了另外一個你根本不知道的地方出現問題。各個代碼庫的合併授權下發給相關的組長,這樣就解決了放權的問題,我們可以把研發部拆成很多的小組,他們可以獨立進行自己的工作,不再受整個研發部統一的授權。

規範了代碼的合併流程,這實際上解決了開發階段的代碼污染問題,包括開發階段的代碼污染、測試階段的代碼污染、以及線上的代碼污染。

對上百個資源節點以微服務爲單位進行分組管理,減少了各個模塊之間的運維干擾,運維也可以以微服務爲單位進行拆分放權,包括進行升級。

部署就可以以接口爲單位,用接口隨意切流量,雖然做不到智能的流量控制,但是如果線上某一個接口造成特別大的壓力,可以讓接口先返回一些友好的報送信息,從而解決線上某一個接口壓力過大的問題。

img

第一,系統在不斷地進步,每一個公司的系統都有不同的階段,要針對現階段找到最佳的解決方案。

第二,所有的道理大家都懂,每個人心中也都有解決方案,當你遇到問題的時候肯定有自己的想法,但是最核心的、最重要的事情就是幹!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章