研發協同平臺架構演進

lcyhjx發表於2019-07-14

導讀

系統架構是一個系統的靈魂,然而一個好的架構(或者更確切的說,一個合適的系統架構)不是一蹴而就,一下子就能完全設計出來的,而是隨著系統發展,逐步演進的。本文將介紹明源雲研發協同平臺的架構從0到1,逐步隨著業務發展一步一步迭代演進的過程。

背景

隨著公司的ToB業務發展,開發團隊規模不斷擴大,需要交付的業務也不斷增長,在這個過程中,交付的效率和質量出現了不同程度的問題,雖然也有QA團隊制定的流程規範以及一些相應的保障措施,但是在交付壓力下,效果不那麼盡如人意。在此背景下,研發協同產品被提上日程,最初的目的就是為了提升整個交付鏈條的效率和質量。研發協同平臺提供從“需求->開發->構建->程式碼質量->測試→釋出”的全鏈路的一站式服務,基於敏捷研發、持續整合、持續交付、DevOps等研發理念,主要是為開發團隊賦能,提升交付效率和質量。

技術選型

技術選型是一個專案的基礎,一旦技術選型出現問題,後期要換用其他技術棧,代價是非常大。一般情況下,技術選型會遵循以下幾個原則:

  • 選擇熟悉的技術 - 一個新專案最好不要使用超過 30% 的新技術,對於不誰的技術,不可能控制使用過程中出現的風險。而且從團隊建設上,任何一位技術 Leader,如果不能得到下屬的技術尊重,必將受到懲罰。當然也不能完全不用新技術,完全不用,勢必會走向走向另一個極端,裹足不前,失去技術前進的機會。總的來說,選擇熟悉的技術,保持穩定性,同時適當引入新技術,保持技術先進性。
  • 選擇成熟活躍的技術 - 選擇成熟的技術,可以避免踩不必要的坑,碰到問題,也可以找到豐富的資料,也可以得到更多的社群支援。當然這是針對應用場景而言,也有一些團隊專門就是做新技術預研,專門去踩坑,看是否有應用新技術的可行性。技術不光是考慮成熟度,還要考慮技術活躍度,活躍度在某個角度也間接說明了技術的應用廣度,同時也能得到更多的支援。
  • 選擇前進的技術 - 選擇一個技術的最低標準是,技術的生命週期必須顯著長於專案的生命週期。為什麼需要確保所選擇的技術不斷前進?因為當前技術發展是非常快速的,技術的前進不僅僅取決於它本身,也和大環境發展密切相關。例如早期的delphi, silverlight, 現在都已被淘汰,如果不幸選擇了類似這樣的技術棧,對專案的傷害是巨大的,甚至可能直接導致專案無法進行下去。總的來說,好的技術棧要永遠跑在使用者需求前面。

基於以上的技術選型原則,研發協同平臺的技術選型如下:

  • 應用技術選型:.Net Core, ABP, EF Core,SQL Server
    選型理由:團隊開發人員都是.NET開放背景,.Net Core 2.0已釋出,已經比較成熟穩定,相較於.Net Framework,不僅跨平臺,而且開源,社群活躍度相當高。ABP是一個開源的.NET/.NET Core的基於DDD的快速應用開發框架,社群活躍度高,版本迭代快,一直在向前。最重要的一點,是這些技術棧都有團隊成員有成功的實施經驗。
  • CI/CD工具鏈技術選型
    需求管理 - JIRA
    程式碼託管- Gitlab, sourcetree
    持續整合 - Jenkins, webpack, grunt
    持續部署 - docker
    質量服務 - sonarqube, dotcover, nuint, xunit, jmeter,selenium
    選型理由:團隊除了在docker上的應用經驗有所不足外,其他的技術都是非常成熟的。docker技術,團隊雖然也有一定的技術基礎和應用經驗,但沒有像研發協同這種大規模的生產應用,並且要同時支援windows和linux容器。研發協同平臺的產品特性決定了,會有大量開發團隊的測試環境執行在平臺下,docker是最符合產品需求的技術。所以即使有風險,也必須選擇docker,同時也是必須啃下的骨頭。

單體架構

在專案初期,為了產品快速上線、快速驗證,架構是比較簡單直接的,就是單體架構,如下圖:
研發協同平臺架構演進

單體架構實現了主要的核心功能,提供了一站式的從需求->程式碼管理->開發->持續整合的服務。整體架構就是展示層->應用服務->資料層,其中快取,後臺作業,排程,郵件,日誌,許可權控制等都是以功能模組的形式內嵌在應用服務中,對於在CI過程使用到的工具棧,也是直接呼叫第三方的服務。另外因為CI過程一般都是長時任務,對於在展示層顯示CI的過程狀態,也是採用了簡單的輪詢機制來處理。
單體架構快速了實現了產品的核心功能,可以提供給種子使用者快速驗證,但隨著驗證反饋->快速迭代,一旦產品提供給大範圍的使用者使用,這種架構也就不在滿足需求了,它的主要問題如下:

  • 業務服務和基礎功能服務耦合在一起,一方面影響業務服務的擴充套件,另一方面基礎服務是公共的,除了為RDC平臺提供服務,在技術上也需要為其它產品提供服務
  • 業務服務中有不少長耗時的任務,這些都影響了業務服務的橫向擴充套件,長耗時任務也必須從業務服務解耦
  • 輪詢機制的狀態重新整理需要改進,同時應用服務和基礎服務拆分後,也需要機制保障通訊,缺少訊息服務中介軟體
  • 不管是從穩定性還是可用性考慮,服務都必須可擴充套件
  • 一旦大範圍使用,Jenkins單點,docker單點服務,都不足以應對,一定要叢集

面對上述問題,平臺的架構也必須升級來滿足業務業務發展的需求,而演進的主要方式則是服務化、叢集化

架構演進的五條原則

既然要對架構進行升級重構,那麼有沒有一些基本的準則,指導我們避免一些坑呢?基於此,我們嘗試總結了架構演進的五條原則:

  • 確定當前的架構現狀:每次架構演進,一定是針對當前架構的,所以必須非常清楚當前的架構現狀和問題。清楚現狀,明白目標,才能逐步改進,向目標前進。
  • 確定重構的目的和必要性:架構重構的原因是什麼?是為了滿足業務需要還是隻是覺得架構比較落伍?除了架構重構之外,是否有別的備選方案,是否一定要進行架構重構?
  • 定義“重構完成”的標準:為每一次架構演進定義清晰的重構目標和成功標尺。
  • 漸進式重構:儘量將重構過程進行分解,每次都進行小的改進,儘快展示成果並得到反饋,在迭代中逐步完善。
  • 遠離虛的東西:例如使用熱門的技術,使用不成熟的技術。架構重構要腳踏實地,根據實際需要以及團隊的技術背景,合理的選擇重構方案。

我們每次對架構的重構,都是按照這些原則來進行的。

向叢集架構演進

單體架構有不少問題,但是否一定需要進行架構重構呢?在重構前,我們需要回答架構演進原則提出的問題:

  • 確定當前的架構現狀:所有服務集中在一起執行。
  • 確定重構的目的和必要性:隨著產品的逐步推廣,使用使用者增多,使用頻率,單體架構在應對業務量上漲上已經越來越吃力,同時,可用性也成為了高風險點。
  • 定義“重構完成”的標準:讓架構支撐服務化,叢集化。
  • 漸進式重構:以迭代的方式,按優化級逐步重構。例如,jenkins叢集化,docker叢集化,基礎服務解耦服務化,一步一步,每一步都可以看到效果,得到反饋。
  • 遠離虛的東西:並沒有引入多少新的東西,主要是解耦,服務化,叢集,增加訊息服務中介軟體。

除了原有的架構重構外,在產品層面, 整個交付鏈條延伸到了C/D環節,這裡和其他DevOps平臺一個很不一樣的點就是,在研發協同平臺上交付的產品是ERP產品,ERP產品是執行在大量客戶的不同環境下的,它不是交付一個SaaS產品,一個雲服務產品。ERP產品要持續交付給大量的不同客戶,而這裡的客戶環境又各不相同,要做到穩定,持續的交付是有相當大的難度和挑戰的,在架構設計上必須充分考慮C/D的穩定性和持續性。

基於以上的需求,我們將單體架構重構為叢集架構,並增加了C/D的架構設計,架構圖如下:
研發協同平臺架構演進

叢集架構有如下特點:

  • 解耦了基礎服務與業務服務,各個服務的職責更清晰,也更單一
  • 基礎功能服務化,複用基礎服務能力
  • 使用Azure檔案雲服務,提高檔案服務的可靠性和可用性
  • 新增訊息服務,解耦各元件之間的通訊
  • 構建服務叢集,提高服務的可靠性和可用性
  • 構建Jenkins叢集,提高平臺的持續整合能力
  • 構建docker服務叢集,提高平臺持續部署,持續提供穩定執行環境的能力

實現了叢集架構以後,服務的能力,穩定性和可靠性都上了一個臺階,但是隨著使用者的使用越來越深入,平臺提供的服務越來越多,叢集架構的問題也逐步開始顯現:

  • 平臺提供的服務能力越來越多,業務越來越複雜
  • 服務雖然叢集化,但是業務服務能力還是單一對外,某個服務功能出現問題,會影響到服務整體對外提供的能力。可行的途徑是進行服務拆分,不過服務拆分,複雜度也會增加,服務的運維成本以及治理問題也是需要綜合考慮的
  • docker容器採用自開發的叢集分配策略,缺少編排能力
  • 平臺服務要提供整合與被整合的能力,與其他的CI服務整合,與測試平臺整合
  • 平臺要與其他產品打通 - 與運維產品打通,獲取客戶運維資料,做到DevOps閉環,通過反饋和運維資料反向推動產品持續迭代改進
  • 平臺要對外開放,面向生態合作伙伴提供服務能力,對外開放,第一步就是要讓使用者能進來,這就涉及到整個使用者中心體系的建立,使用者管理、統一身份認證等。
  • 雖然叢集架構已大大提高了可靠性和可用性,但是隨著服務的深入使用和使用者規模的不斷增長,對可靠性和可用性的要求也越來越高,對平臺服務以及服務資源的運維也變得越來越重要和緊迫

面對上述問題,需要對服務進行拆分,治理,提供服務和資源的運維、監控能力,而都需要架構

向微服務架構演進

在進行微服務架構重構之前,我們同樣需要回答架構演進原則提出的問題:

  • 確定重構的目的和必要性 - 隨著產品的持續迭代,業務複雜度越來越大,服務的使用也越來越深入,使用者規模也在不停的增長,對整體服務的可靠性,可用性提出了新的挑戰
  • 定義“重構完成”的界限 - 微服務化,容器雲平臺
  • 漸進式重構 - 以迭代的方式,按優化級逐步重構。例如服務的運維,監控,日誌服務,服務的拆分,治理,容器雲平臺這些都是獨立可逐步改進的
  • 確定當前的架構狀態 - 叢集架構中已經詳細的描述
  • 遠離虛的東西 - 新引入的技術點都有成熟可借鑑的方案,例如k8s,ELK,grafana, IdentityServer4,Ocelot,Consul

但是這裡有一點是要特別強調的,儘管新引入的技術都有成熟可借鑑的方案,但是對團隊而言,有不少是沒有成功的生產環境實施經驗的,這裡是冒了一定的風險,但又是不得不去做和突破的事情。
重構後的微服務架構圖,如下:
研發協同平臺架構演進

微服務架構的特點如下:

  • 提煉CI引擎,豐富整合能力
  • 服務按領域拆分,提供服務治理能力
  • 服務運維能力,提供監控、告警、統計分析
  • 提供日誌服務,便於錯誤分析和運營分析
  • 提供統一的容器雲服務, 提供高可用、可伸縮的容器應用管理

各個應用層在微服務架構下的職責:

  • 執行環境層:提供基礎設施服務,包括伺服器,IT安全配置以及容器雲平臺。未來所有的服務都會執行在容器雲平臺上,當前只有少數的服務在容器雲平臺上試執行,隨著不斷的改進、成熟,未來會逐步將服務遷移到容器雲平臺上
  • 資料儲存層:提供資料儲存能力,對於不同的資料型別,提供了不同的儲存方式。 Sql Server用於應用資料的儲存,redis用於快取資料的儲存,ES叢集用於日誌的儲存,Azure檔案用於文件的儲存
  • 基礎服務層:提供基礎公共服務能力,除了為研發協同平臺本身提供基礎服務,也面向其他產品提供基礎服務能力。
    日誌服務(ELK)提供日誌採集,儲存,分析和展示服務;
    訊息服務(MQTT)提供元件間的通訊能力;
    檔案服務(Azure檔案)為應用提供統一的上傳、儲存、下載的服務;郵件服務提供郵件傳送服務;
    任務排程和後臺作業(Quaz+Hangfire)提供了長耗時任務佇列的排程和處理服務;
    身份認證服務(IdentityServer4)面向開放提供了統一的身份認證能力。
  • 應用服務層:研發協同業務服務,主要包含基礎服務,產品服務,持續整合服務、質量服務和持續交付服務。當前應用服務還沒有微服務化,還處於服務拆分階段,按領域拆分,按檔案結構組織,一旦微服務框架就緒,則按領域服務一個一個拆分,逐步切換。
  • API介面層:API閘道器為服務消費端提供了統一的服務入口。除了閘道器,實現微服務框架,還必須實現服務治理:服務的註冊、發現、負載、容錯、降級、監控與日誌。
  • 展示層:展示層是應用服務的消費者,通過API閘道器來使用應用服務。
  • 運維監控:運維監控服務(App.Metric+telegraf+InfluxDB+Grafana)當前主要實現了伺服器資源監控以及業務服務的監控(流量、請求、錯誤等),以及分析圖表的展示,並根據一定的預警規則,即使預警異常。

微服務架構是我們今年技術規劃要實現的目標,其中一部分已經落地,一部分正在進行,也有一些還未開始,隨著產品業務的發展,伴隨著架構也是在不斷摸索、重構、演進、向前。

寫在最後

從來沒有一個完美的架構能夠一直支撐業務的發展,架構是動態的、變化的,隨著業務的發展不斷演進的,不同的階段需要不同的架構 。研發協同平臺的架構也是經歷了單體架構->叢集架構->微服務架構幾個階段,而且每一次架構重構週期都比較長,只要架構的模式思路定下來,保持快速的敏捷演進,不停向前,結合反饋和實際應用情況,不斷改進,就可以比較穩定的實現架構重構。

相關文章