邁向雲原生:FreeWheel 應用架構演進

01 何爲雲原生應用

2010 年,WSO2 的創始人 Paul Fremantle 提出了雲原生(Cloud native)一詞。經歷了 10 多年的發展和技術變革,雲原生的定義和內涵都有了很大的變化。目前,雲原生計算基金會(CNCF)對 “雲原生” 的定義如下:

該定義強調了應用要部署在以云爲載體的動態環境中,即生而爲雲,同時列舉了 5 種核心的雲原生技術。基於此定義,我們可以認爲:運行在雲上(無論是哪種雲)且使用了以上一種或多種技術構建的應用就是雲原生應用。

這樣的理解固然沒錯,但流於表象,我們希望能通過雲原生技術的內在理念以獲取更深層次的理解。

雲原生應用是不斷變化和演進的

從本質上講,雲平臺提供的核心能力是複製(Replication),可以將各種類型的工作負載以手動或自動的方式進行復制和銷燬,從而讓應用具有彈性伸縮的能力。

因此,雲上應用比傳統應用更容易擴展,在規模和外部形態上是動態變化的(基於流量需求)。這是雲原生應用之於傳統應用比較大的區別。

我們再來看看雲原生的代表技術——微服務。作爲一種應用架構,它可以讓每個服務獨立開發、部署、運行。除去解耦的優點,這種構建方式可以讓應用按需迭代,像細胞分裂再生一般不斷更新,實現所謂的演進式設計。這一特性使得應用在內在的組織結構上也是動態變化的。而不可變基礎設施(如容器、Pod)讓這一變化方式更易實現。下圖展示了一個微服務應用的各個組成部分都可以獨立演進,且每一個服務自身也可以基於需要獨立擴展。

因此,從技術特性的角度來看,雲原生應用所具有的一大特點就是在外部形態和內部結構上都是動態變化的。

雲原生應用以業務構建爲核心

構建一個分佈式系統通常要實現 3 部分內容:業務邏輯、控制邏輯、技術框架。

業務邏輯是重中之重,是爲客戶實現商業價值的核心所在,也是主要的開發活動。

控制邏輯用來輔助業務邏輯完成一些特定的需求,我們稱之爲非功能性需求,比如把數據切分成多段進行傳輸、用循環實現一個重試功能等,控制邏輯通常會利用中間件、類庫的方式實現複用。

技術框架提供了封裝好的模型、流程和工具庫,提升了開發效率。當然框架並不是必須的,完全可以基於語言特性直接開發應用。

這 3 部分工作中其實只有業務邏輯是客戶所要求的,即實現客戶的商業價值。但因爲應用在性能、可用性、可擴展性等一系列質量屬性的需要,我們不得不開發一系列的和業務無關的非功能性需求,這些屬於額外的工作,而且這些工作的開發時間佔比很可能超過了業務本身。

我們再來看看雲平臺、雲原生技術帶來了什麼。

從 2006 年 AWS 推出 EC2 到現在,雲平臺的職能發生了巨大的變化。一開始它只能提供單一的計算資源,應用開發的整個流程和依賴項依然需要開發人員實現和管理。

而現在,雲平臺的計算、存儲、網絡、安全等各種資源和能力面面俱到,大量的非功能性需求都下沉到了基礎設施層面,比如通過服務網格輕鬆實現超時重試這樣的流控能力。

下圖展示了雲平臺的職能演進過程,越來越多的資源、特性、能力都可以通過雲平臺實現,開發者只需要管理好自己的數據,即業務本身。

因此我們認爲,雲原生應用應該是以業務構建爲核心,利用雲的能力獲取、而不是自己開發非功能性需求,從而讓開發過程變成純粹而高效。

02 雲上創新

應用構建需要遵循流程,應用演進亦是如此。亞馬遜雲科技提出的現代化應用構建(MAD)理論是開發雲原生應用的實踐方法,它將應用構建分爲了 3 個階段。

FreeWheel 正是這一方法的踐行者,完成了從單體到微服務、遷移上雲、雲原生應用的改造實踐。

應用平移

在應用平移階段,我們主要做了兩件事:首先是單體應用到微服務的改造,這個過程中我們用到了 “絞殺者” 模式;然後是容器化。

“絞殺” 單體應用

FreeWheel 早期的核心業務系統是基於 Ruby 構建的單體應用,運行了 10 年之久。隨着業務特性不斷的增加,應用變得龐大而臃腫,Ruby 和 JavaScript 總代碼行數超過了 100 萬行,添加新功能和對既有功能的維護都變得舉步維艱。

2017 年團隊着手對系統進行微服務改造,技術棧也隨之遷移到以 Golang 爲主的開發語言。爲了快速上線新服務,儘快擺脫複雜單體在部署維護方面的痛點,我們使用了絞殺者模式進行遷移。

絞殺者模式的優勢就在於它是一種漸進的過程,容許新舊系統共存,並給予新系統成長的時間。它的另一個優點是能夠降低風險。一旦新系統無法工作你可以迅速的把流量切換回舊系統。

絞殺者應用的開發過程也有三個階段:

下圖展示了這一過程。

我們對舊系統的改造工作包括前端和後端兩部分,後端部分是把原來的業務邏輯逐一拆解成微服務;前端部分是把原來的 Rails 應用重構爲基於 React 的 UI 界面並調用微服務提供的新接口。

應用容器化

在完成應用微服務改造的同時,另一件上雲的準備工作就是應用容器化。微服務讓應用具有了按需演進的能力,容器這種能力變得更易實現。

一方面,容器容許我們使用更小的計算單元,降低構建成本;另一方面,容器對齊了應用的構建標準,讓不同團隊、基於不同技術棧的服務以統一的方式部署運行,簡化了對基礎設施的維護,並讓 CICD 流水線的構建變得統一和便捷。

根據 CNCF 2020 年的問卷調查顯示,超過 90% 的組織和團隊都已經使用容器進行應用的構建和部署。應用程序容器化已經成爲業界標準。

雲上重構

容器化僅僅是基礎,應用還需要通過編排實現生命週期管理。團隊選擇了 AWS 託管的 Kubernetes 產品 EKS 作爲容器編排和管理平臺。到目前爲止,我們已經創建了 16 個集羣,總 Pod 數量超過 5000 個。

首先針對應用特性選擇對應的資源類型,比如最常用的無狀態服務使用 Deployment,有狀態服務選擇 StatefulSet,守護進程選擇 DaemonSet,任務相關的選擇 Job、CronJob。然後將服務暴露出去使得集羣內或者集羣外能夠訪問。

**進入應用的外部流量有兩種:**一種是頁面訪問,另一種是 OpenAPI。

爲了控制外部流量我們使用 API Gateway 作爲入口網關,除基本的路由外,還實現了鑑權和限流等功能。

**內部流量也有兩種:**一種來自集羣外部,其他存量系統對應用的訪問,我們會使用 ExternalName 與 Route53 DNS 域名綁定來實現;另外一種就是微服務之間的調用,可以直接通過服務名方式訪問。

隨着微服務的不斷增多,服務之間的調用拓撲也越加複雜,流量控制、治理和監控等需求也越來越重要。

在經過調研和探索之後,我們在應用中引入了 Istio Service Mesh 管理服務間的流量。通過它我們實現了按類型的流量切分,將來自頁面和 API 的請求分發到不同的 Endpoint 去處理;而超時、重試、熔斷這些彈性能力也可以通過聲明式配置實現,無須手動編寫控制邏輯。

**在存儲層面上,**我們也做了重構,基於數據特性選擇最合適的解決方案。比如把廣告庫存信息這樣的元數據遷移到了 NoSQL 鍵值數據庫,以提升其查詢效率。

**另一方面,**與監控平臺的整合讓微服務應用的可觀察性獲得極大提升。應用的業務日誌和請求日誌都會存儲在 ELK 中,流量指標也統一收集到監控平臺的 Prometheus 系統,並通過 Grafana Dashboard 展示。我們還基於 Jaeger 構建了一個分佈式追蹤系統,可以方便地查看服務的調用鏈路並進行根因分析。

下圖展示了 CNCF 定義的雲原生核心技術。至此,雲原生應用形態逐漸清晰。從微服務架構、容器化,到 Kubernetes 容器編排,再到使用 Service Mesh 實現流量控制,應用已經使用了所有云原生定義中的核心技術。

構建新應用

在應用架構不斷完善的同時,我們還積極探索更加靈活和輕量級的 Serverless 解決方案,通過 AWS Lambda 實現了特定場景的業務需求。

**這些業務場景通常都有一個共性:**一般是異步的、計算型的任務,不需要實時在線。

爲這種業務構建一個微服務顯然不合理(異步、離線計算任務不需要實時在線,運行完即結束,一個總是在線的守護進程服務空閒時間太多,浪費資源)。而 Serverless 按需啓動、根據流量自動伸縮的能力非常適合這些場景。經過對比測試,我們發現資源成本降低了很多。同時,因爲不需要對服務器等基礎設施進行管理,運維效率也提高了。

除了依賴現有的開源和託管產品構建應用,團隊還開發了一系列的自研平臺,覆蓋應用的構建、運維、監控等方面,可以讓工程師以所及即所得的方式實現應用程序的全生命週期管理。

例如我們開發了一個內部代號爲 Bingo 的低代碼開發平臺(LCDP),可以以可視化方式構建出一個 Serverless 或微服務的代碼框架,並自動生成 CI/CD 流水線。開發人員只需要實現具體業務邏輯即可,極大地減少了框架層面的重複性勞動,提升了開發效率。公司的運維團隊還開發了一個強大的運維平臺 FreeWheel Operation Center(FOC),可以與 Kubernetes 集羣深度對接,完成集羣的監控、部署、更新等運維工作,降低了手動運維出錯概率,提高了運維效率和安全性。

下圖展示了目前核心業務系統的架構形態,準確來說我們的應用已經發展成爲一個微服務加無服務器的混合雲原生架構,並通過 Kubernetes 和 Istio 完成應用編排管理和服務治理工作。

03 未來期許

如果說使用了雲原生技術是構建雲原生應用的第一階段,那麼下一個階段就是以原生的方式開發應用,即在設計思路上優先基於雲原生技術和編程範式進行應用的構建。

比如,利用 Kubernetes 控制器模式以聲明式配置的方式管理應用資源;優先選擇服務網格的能力實現服務治理而不是手動開發控制邏輯;通過服務的可觀察性以開發者視角主動關注應用的運行狀態。

上述這些都需要開發人員擯棄傳統開發習慣,以雲原生的理念設計和方法來構建應用。也只有這樣,才能實現雲原生技術以業務爲核心的願景,迴歸軟件開發的本源。

**《雲原生應用架構:微服務開發最佳實戰》**一書從真實案例出發反推技術難點,匯聚名企一線工程師的真知灼見!一網打盡微服務、雲原生、服務網格、敏捷開發、分佈式事務、無服務器架構、可觀察性、質量保證、CI/CD 等前沿話題,熱點技能各個擊破!

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/RQ51IhvVOxwh62fnBczuog