2018-10-23 FreeWheel業務系統微服務化過程經驗分享
轉載: ofollow,noindex">https://mp.weixin.qq.com/s/JgNgmYasXaTqrx5OeeD5KQ
2016 年下半年開始,FreeWheel 開始將其業務系統從 Rails 單體應用逐步遷移到微服務,同時技術棧從 Rails 改為 Golang,兩年之後,整個遷移接近尾聲,FreeWheel 業務系統技術團隊對外分享了它們在微服務化過程中的經驗。
原有架構的問題
FreeWheel 是一家為客戶提供數字視訊廣告管理技術和服務的公司。其業務端產品需要對接客戶,提供視訊廣告投放優化介面,類似於 Web ERP,該業務系統採用 Rails 技術棧開發,其架構是一個典型的三層架構。

image
這個系統經過近十年的研發和迭代,程式碼量達到數十萬行,業務的特殊性和程式碼的複雜度讓團隊的維護和新功能研發越來越困難:
-
廣告系統本身業務邏輯非常複雜,體現在它的資料實體很多,業務流程很長,分支邏輯很多。這樣導致程式碼修改起來困難,可能改一個會影響好幾個其它模組,同時維護也變困難,後來者不清楚模組具體實現細節,難以接手繼續開發。
-
Ruby 本身是一個高度動態的語言,通過解釋執行。帶來的壞處就是團隊大了,維護成本很高,當發現問題的時候很難通過看程式碼知道問題出在哪兒,而且它也缺乏靜態檢查的工具,導致程式碼質量難以控制。
由於以上這些原因,FreeWheel 架構組決定將系統進行拆分,通過模組化來梳理和簡化業務邏輯,當時微服務已經有不少公司採用,並取得了不錯效果,架構組在調研之後決定採用微服務架構。同時團隊還決定切換技術棧,選擇更利於開發維護的語言和工具,基於種種理由,團隊最後選擇了 Golang。
從 Rails 到 Golang
在實施微服務時,很多團隊都選擇 Java 技術棧,畢竟有 Spring Cloud 等較為成熟的框架可以使用。FreeWheel 選擇 Golang,則基於以下幾個原因:
-
Golang 本身上手門檻較低,有優秀的標準庫可以快速開發應用,同時,Golang 生態也逐漸豐富,有不少大型專案採用;
-
微服務化過程中需要使用容器,FreeWheel 很早就確定使用 Docker 和 Kubernetes 作為容器化技術棧,而這兩者都是 Golang 開發,不管是熟練掌握容器技術,還是要進行一些 K8S 擴充套件開發、定製,使用 Golang 都順理成章;
-
新的技術棧不僅僅是業務系統團隊使用,公司在研發新業務時也會使用,FreeWheel 之前各個系統的技術棧各不相同,有用 C++,有用 Java,也有用 Ruby 的,因此從大家都能接受的角度,Golang 也是一個較好的選擇。
-
公司在美國的技術團隊有過使用 Golang 的經驗,並在內部做過分享,通過這種方式團隊能快速瞭解這門新語言特點,遇到難題也可以向公司內部請教。
值得一提的是,FreeWheel 新的 Golang 應用都是由原來的 Rails 工程師研發的,為了讓這些工程師順利轉移到新的技術棧,公司通過內部分享、黑客鬆等方式幫助團隊成員快速上手,在短時間內即形成了戰鬥力。
遷移策略
FreeWheel 業務系統在決定重構時,新的需求仍然源源不斷的產生,不能把需求停掉轉而研發新系統;同時團隊人力有限,不可能劃出一部分人來轉型微服務研發,因此,團隊在一邊研發原有 Rails 應用的同時,一邊做新的系統研發。
在設計服務的粒度上,因為 FreeWheel 業務系統本身已經有了一套成熟的資料模型,這個資料模型可以反映經營的業務概念,也作為大家共同的語言,圍繞這些資料模型是業務實體,團隊在確認出三到四個核心業務實體後,圍繞這些先建立了大概三到四個服務,最終建立的服務在 10 個左右,服務的粒度其實比較粗。FreeWheel 採用微服務的架構模式,其實主要也是吸收微服務架構中服務治理的一些實踐經驗,在初期服務設計上先從粗粒度開始。
在進行微服務改造時,團隊還面臨一個比較大的問題,就是原有架構使用單個資料庫,裡面有上千張表,資料分支很多,難以進行拆分。為了解決資料訪問問題,專門設計了一個數據訪問層,將原系統和新系統的資料庫連線都通過資料訪問層進行。資料訪問層(內部簡稱 DAL)的設計目標包括:
-
對業務資料的訪問進行全域性路由,控制和優化,比如對不同客戶的資料做軟隔離,讀寫分離等;
-
在不分庫的情況下,實現不同服務對資料的分治;
-
將應用與資料庫具體實現隔離,為今後拆分資料庫以及應用多種資料來源做準備。
其基本架構如下圖所示:

image
最後,FreeWheel 還需要解決上線問題,因為面向大 B 類客戶,需要保證新老系統切換的平滑穩定。在這方面,對已開放的 Open API,FreeWheel 都保證介面和輸入輸入不變,通過新增一層介面卡來將實現切換到新的服務上,同時通過完善的線下測試和 QA,以及線上的灰度釋出來解決,並且,程式碼的單測覆蓋率達到 80% 以上以保證程式碼質量,通過線下流量回放來保證原有系統的業務邏輯能夠順利完成。
微服務技術選型
由於 FreeWheel 業務系統功能較為單一,服務間的複雜互動不多,團隊規模也不大,因此在進行微服務改造時較多依賴 Kubernetes 提供的原生能力,以及在它基礎上開發的擴充套件來滿足需求。
新的微服務架構如圖:

image
具體元件的技術選型如下:
API 閘道器
API 閘道器包括認證、許可權管理、限流、Metrics 等功能,這一部分為自研。它最初是為了將 FreeWheel 的自定義 token 認證切換到 Auth0 而研發的,一開始就是為了滿足需求,逐漸擴展出其它功能,其請求處理流程如下:

image
服務框架
服務框架也為 FreeWheel 原 Rails 團隊自研的輕量級框架,內部代號 Wheels,該框架借鑑了 Rails 腳手架的理念,基於 gPRC 進行了必要的擴充套件,比如在 protobuffer 物件中區分空值和未指定等,並集成了已有的資料訪問,監控,訊息,服務發現等服務,同時提供了一組單元測試,整合測試和麵向 docker 和 kubernetes 的構建工具,使業務開發團隊能快速開發出一個符合公司程式碼質量和服務治理標準的服務,而只需關注業務邏輯本身。下圖展示了 Wheels 框架所包含的主要元件:
image.gif
服務註冊發現
這部分使用的 K8S 原生 DNS 元件 kube-dns,因為服務框架統一,所以無需進行額外配置或使用開源工具。
配置中心
FreeWheel 的配置中心元件基於 K8S 進行擴充套件而來,目前業界比較知名的配置中心開源元件有攜程的 Apollo,但配置中心其實是 K8S 的一個核心功能,其它的開源庫都是在它的 API 基礎上封裝而來。自研的配置中心與其它相比更有可控性,出了問題方便排查,該配置中心也無需面向業務,而由研發和 DevOps 負責操作,因此無需封裝的太多。
資料匯流排
這個使用 Kafka 進行服務間的資料交換。Kafka 也是 FreeWheel 其它業務如大資料平臺重要的基礎設施。
日誌
新的微服務架構裡包含多個日誌,包括 K8S 本身的日誌、服務框架產生的日誌、在業務中埋點產生的日誌等,團隊不僅依靠日誌做監控和告警,也通過日誌來做 debug。對日誌收集處理的系統為 ELK。
監控與告警
使用 Prometheus,前段時間釋出了 1.0 版本,也是目前主流的微服務監控框架。
Service Mesh
使用 Istio,網路治理對於微服務來說是非常關鍵的一環,而 Service Mesh 可以將開發人員從一些瑣碎的關注點中解救出來。FreeWheel 團隊主要利用了 Service Mesh 中的斷路、連線管理、流量接管、自動重試、全鏈路跟蹤、安全等功能。
微服務化成功要素總結
FreeWheel 的業務系統重構實踐,可以說是一個很典型的中小型團隊的微服務改造案例,它的經驗值得其它團隊學習,從中我們可以總結出一些成功經驗:
一、選擇合適的技術棧,可以做到事半功倍,在學習新的技術棧的同時,可以提升團隊的整體實力。
二、對於一些功能較為單一的業務系統,用好 Kubernetes,微服務就成功了一半,團隊裡一定要有對 Kubernetes 非常熟悉、能夠搞定它的各種問題的人。
三、微服務架構很多時候運維和研發已經不太能分的開,需要研發團隊轉型為 DevOps,設計並實現新的運維體系。
四、從自己的需求出發,簡單的以及核心的需求可以自研,較為複雜的可以採用開源庫,在研發能力和效率之間取得平衡。
受訪嘉賓
張晗,現任 FreeWheel 首席架構師,全面負責核心業務系統開發,目前專注於業務系統的微服務化改造。
羅昕,現任 FreeWheel 首席工程師,目前負責公司微服務框架的開發工作。
楊諭黔,現任 FreeWheel 高階工程師,主要從事容器化相關的開發和推廣工作。