導讀
系統架構是一個系統的靈魂,然而一個好的架構(或者更確切的說,一個合適的系統架構)不是一蹴而就,一會兒就能徹底設計出來的,而是隨着系統發展,逐步演進的。本文將介紹明源雲研發協同平臺的架構從0到1,逐步隨着業務發展一步一步迭代演進的過程。linux
背景
隨着公司的ToB業務發展,開發團隊規模不斷擴大,須要交付的業務也不斷增加,在這個過程當中,交付的效率和質量出現了不一樣程度的問題,雖然也有QA團隊制定的流程規範以及一些相應的保障措施,可是在交付壓力下,效果不那麼盡如人意。在此背景下,研發協同產品被提上日程,最初的目的就是爲了提高整個交付鏈條的效率和質量。研發協同平臺提供從「需求->開發->構建->代碼質量->測試→發佈」的全鏈路的一站式服務,基於敏捷研發、持續集成、持續交付、DevOps等研發理念,主要是爲開發團隊賦能,提高交付效率和質量。webpack
技術選型
技術選型是一個項目的基礎,一旦技術選型出現問題,後期要換用其餘技術棧,代價是很是大。通常狀況下,技術選型會遵循如下幾個原則:web
- 選擇熟悉的技術 - 一個新項目最好不要使用超過 30% 的新技術,對於不誰的技術,不可能控制使用過程當中出現的風險。並且從團隊建設上,任何一位技術 Leader,若是不能獲得下屬的技術尊重,必將受到懲罰。固然也不能徹底不用新技術,徹底不用,勢必會走向走向另外一個極端,裹足不前,失去技術前進的機會。總的來講,選擇熟悉的技術,保持穩定性,同時適當引入新技術,保持技術先進性。
- 選擇成熟活躍的技術 - 選擇成熟的技術,能夠避免踩沒必要要的坑,碰到問題,也能夠找到豐富的資料,也能夠獲得更多的社區支持。固然這是針對應用場景而言,也有一些團隊專門就是作新技術預研,專門去踩坑,看是否有應用新技術的可行性。技術不光是考慮成熟度,還要考慮技術活躍度,活躍度在某個角度也間接說明了技術的應用廣度,同時也能獲得更多的支持。
- 選擇前進的技術 - 選擇一個技術的最低標準是,技術的生命週期必須顯著長於項目的生命週期。爲何須要確保所選擇的技術不斷前進?由於當前技術發展是很是快速的,技術的前進不只僅取決於它自己,也和大環境發展密切相關。例如早期的delphi, silverlight, 如今都已被淘汰,若是不幸選擇了相似這樣的技術棧,對項目的傷害是巨大的,甚至可能直接致使項目沒法進行下去。總的來講,好的技術棧要永遠跑在用戶需求前面。
基於以上的技術選型原則,研發協同平臺的技術選型以下:redis
- 應用技術選型:.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,同時也是必須啃下的骨頭。
單體架構
在項目初期,爲了產品快速上線、快速驗證,架構是比較簡單直接的,就是單體架構,以下圖:
docker
單體架構實現了主要的核心功能,提供了一站式的從需求->代碼管理->開發->持續集成的服務。總體架構就是展現層->應用服務->數據層,其中緩存,後臺做業,調度,郵件,日誌,權限控制等都是以功能模塊的形式內嵌在應用服務中,對於在CI過程使用到的工具棧,也是直接調用第三方的服務。另外由於CI過程通常都是長時任務,對於在展現層顯示CI的過程狀態,也是採用了簡單的輪詢機制來處理。
單體架構快速了實現了產品的核心功能,能夠提供給種子用戶快速驗證,但隨着驗證反饋->快速迭代,一旦產品提供給大範圍的用戶使用,這種架構也就不在知足需求了,它的主要問題以下:windows
- 業務服務和基礎功能服務耦合在一塊兒,一方面影響業務服務的擴展,另外一方面基礎服務是公共的,除了爲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)當前主要實現了服務器資源監控以及業務服務的監控(流量、請求、錯誤等),以及分析圖表的展現,並根據必定的預警規則,即便預警異常。
微服務架構是咱們今年技術規劃要實現的目標,其中一部分已經落地,一部分正在進行,也有一些還未開始,隨着產品業務的發展,伴隨着架構也是在不斷摸索、重構、演進、向前。
寫在最後
歷來沒有一個完美的架構可以一直支撐業務的發展,架構是動態的、變化的,隨着業務的發展不斷演進的,不一樣的階段須要不一樣的架構 。研發協同平臺的架構也是經歷了單體架構->集羣架構->微服務架構幾個階段,並且每一次架構重構週期都比較長,只要架構的模式思路定下來,保持快速的敏捷演進,不停向前,結合反饋和實際應用狀況,不斷改進,就能夠比較穩定的實現架構重構。