大數據

螞蟻開發框架編年史

前言
螞蟻的開發框架已經發展了十幾年,下面有 SOFA/CE/SOFABoot/SOFAMVC 等多個產品,這些框架已經深入到各個基礎應用、業務應用,甚至我們的合作伙伴、客戶。那為什麼有這麼多開發框架呢?為什麼開發框架長現在的樣子呢?讓我們來了解下它們的過去、現在和將來吧!
PS:由於部分歷史太過悠久,如果發現有錯誤,歡迎指正。

**
為什麼要有開發框架**

在介紹歷史之前,我先簡單介紹下為什麼會產生開發框架這個產品,解決了什麼問題。
大家知道軟件系統隨著業務的發展,會變得越來越複雜,不同業務領域所涉及到的技術會很多。不同的業務用到技術有很多共同性的基礎服務,也有很多差異化的業務服務。如果每次一個有一個新的業務系統,都從頭開始搭建工程,那都是一個比較複雜的事情,且並不一定能將它做好。另外如果大家的工程沒有統一,那麼團隊協作開發時,沒有了統一標準,大家都隨意發揮,同樣的重複的功能到處都是,同類型的代碼放到不同的地方。由於沒有統一規範,一個人很難看懂別人寫的代碼,當出現Bug或維護時,根本無從下手。
  而開發框架,會提供模板化的代碼,提供可複用的基礎能力,讓業務同學只需要專心的實現所需要的業務邏輯就可以了,而很多底層功能框架已經通過集成不同的組件幫我們很好的實現了,這樣團隊的開發效率就能提高。另外對於一個人維護多個產品,或者團隊成員變動,或者跨團隊技術交流,都不用擔心大家溝通和理解上的問題,統一的代碼規範能讓我們能輕鬆的看懂其他人寫的代碼。
小結:
開發框架提供代碼模版,對齊大家的溝通概念,例如模塊、分層、日誌等,降低溝通協作成本,降低學習成本;
開發框架提供統一的編程界面,提供可複用的功能組件,減少大量重複代碼的編寫,提供開發效率;
開發框架提供可擴展能力,讓更多的通用能力可以沉澱下來給其它人員使用,也可以讓更多用戶進行二次開發;
統一的開發框架可以統一發布、運維、監控體系,無需重複建設這些能力;
統一的開發框架可以拉齊大家的技術風險和安全風險水位,快速進行統一風險識別和消除。

SOFA 系列開發框架的歷史

SOFA1 - 2007
最早的支付寶是一個非常大的單應用,很多團隊會一起在上面開發功能,痛點就是各種代碼合併衝突、spring bean 命名衝突等等。
那 SOFA 第一代是 2007 年研發的,主要就是通過 Spring 上下文隔離做的模塊化,去解決多人協作開發的問題,不同的模塊開發者打成自己的二方包,每個模塊可以有獨立的上下文,無需關心各種 bean 配置衝突等。
DD400507-3815-43e7-A437-E96EE9CF43AE.png

SOFA2 - 2009
第二代的背景是 2009 年整個集團包括支付寶都在做 SOA 化,主要就是基於 HSF 的分支提供了 TCP 遠程調用的能力。在 SOFA2 裡,也集成了註冊中心、配置中心等中間件。
2.png

SOFA3 - 2011
JBoss 的功能非常多比較重,SOFA2 只用了 JBoss 裡面非常少的能力,另外希望在一個容器下部署多個應用的需求。所以在 2011 年,就研發了 CloudEngine(下稱 CE) 替換了 JBoss,並提供將多個 SOFA 應用部署在同一個 CE 容器裡的能力,即合併部署1.0。
SOFA3 開始首次提供了健康檢查的能力,給 paas 層提供了統一的完整的監控調度接口。
SOFA 3 開始在設計的時候參考 OSGI 的思想,將中間件的 classloader 類跟業務的 classloader 進行了隔離,還參考 OSGi 模型將一個個模塊定義為 bundle,這個概念也一直影響到現在。由於 bundle 的推出,此時有大量的二方包採用這樣的 jar(包含代碼 + xml 配置)。
為了將應用部署到 CE 上,將應用程序打包成一定的目錄結構,也就是 ace 包,這個結構目前也一直在使用。

SOFA4 - 2014(維護中)
SOFA3 時代,CE 和 SOFA 還有眾多的中間件都是在一個 repo 裡開發的,另外 bundle 的概念也無法區分。所以 SOFA4 最早做的就是代碼拆分,將各個中間件組件從一個代碼倉庫變成多個代碼倉庫,內部和外部的邏輯也分開到不同的倉庫下,你可以認為 SOFA 框架、SOFARPC、MSG 這些都是獨立的 CE 的插件,最終打包的時候再把這些插件打包到 CE 裡。Bundle 的概念也被一分為二,中間件等作為 CE 插件,而業務的我們作為是 SOFA 模塊。
在接下來的幾年,SOFA4 也跟著業務場景一起做了很多能力,這些能力都不僅僅是框架本身,而是要推全部的 CE 插件去支持的,包括:
Bolt 協議升級,QPS 提高 120%
JDK8 支持、Log4j2 支持
接入 Tracer 埋點、Ambush 切面埋點
支持合併部署 2.0,將鏈路應用軟隔離
接入 Metrics,提供統一的度量出口
動態模塊,支持將模塊動態部署到 CE 中
日誌異步化,支持混部機房離線在線混部。
模塊異步加載、並行加載,提高啟動速度
另外一個問題就是,跟 SOFA3 時代一樣,提供通用能力的二方包大量採用 SOFA 模塊的形式提供,這種形式下 jar 裡包含代碼 + spring xml 配置,使用者只需要加依賴即可,無需額外配置,不會有 bean 衝突的問題,這就導致這種存量的近端包很多,使用範圍甚廣。

SOFAMVC4 - 2014(維護中)
由於 SOFA 框架支持 Spring 上下文隔離,管控了應用的生命週期,為了讓 Spring MVC 能夠在 SOFA 框架上運行,我們開發了 SOFA MVC 框架,SOFAMVC 有幾項 Spring MVC 不存在的基本能力:
兼容 SOFA 上下文隔離能力,MVC 的 ApplicationContext 與應用其他近端包 ApplicationContext 隔離
兼容 SOFA 框架事件機制,能夠監聽 SOFA 事件並刷新應用 MVC ApplicationContext
兼容 SOFA 健康檢查能力,能夠將 SOFA MVC 上下文刷新失敗事件返回 SOFA 框架
有以上三個能力,SOFAMVC 就可以在 SOFA 環境使用了——能刷新 ApplicationContext、能返回刷新結果並且支持 sofa service 和 sofa reference 標籤。除了以上基本能力,SOFAMVC 還開發了一套插件擴展機制,幫助用戶更好得擴展 SOFAMVC。SOFAMVC 插件除了提供了 class 資源外,還支持組件(Spring bean)的聲明,在“SMVC-INF/advise/”目錄下可以定義spring相關配置文件,比如 session 插件,在這裡定義了 session 存儲的工廠類的聲明。SOFAMVC4 支持以下插件列表(部分):
mvc-security-plugin:提供了常用的 Web 安全能力的插件
mvc-alipay-auth-plugin:提供了 authcenter 登錄鑑權能力的插件
mvc-tair-session-plugin:提供了分佈式 session 能力的插件
mvc-json-plugin:提供 Json 請求處理能力
mvc-widget-plugin:提供了頁面局部(tile)跨 car 本地或跨項目遠程的複用技術
mvc-resource-plugin:提供了封裝了資源上傳、下載的插件
SOFAMVC4 同時支持 SOFA3 和 SOFA4 框架,SOFA3 框架運行在 Spring3 上,SOFA4 框架運行在 Spring4上,為了讓 SOFAMVC4 同時支持兩個版本,SOFAMVC4 的核心代碼都是基於 Spring3 進行改寫的,所以 @RestController 、@CrossOrigin 等 Spring 高版本才引入的註解在當前的 SOFAMVC4 上都是不支持的。
可以看到 SOFAMVC 的發展脫離了 SpringMVC 社區一些發展,未及時同步最新特性,所以很多 SpringMVC的能力已經不能支持,這是比較大的問題之一。隨著前後端分離的推廣,SOFAMVC 也逐漸會退出歷史舞臺。

SOFALite - 2014
2014年,螞蟻技術開始通過金融雲對外輸出,由於 SOFA/CE 的組合太重了,不適合對外輸出,所以需要非常輕量的場景對接螞蟻中間件雲上服務的產品。基於接入成本的考慮,選擇開發了一個 Spring + SDK 的 SOFALite1 版本供用戶接入。由於只有部分應用接入,未大規模推廣,這裡就不多介紹了。
SpringBoot 是在 2014 年 4 月份發佈 v1.0.0,在 2015 年的時候慢慢在圈內流行起來。

SOFABoot2 - 2016
2016 年開始基於 SpringBoot 1.x 研發 SOFALite2,當年 SOFALite2 上線,正式對外商業版客戶使用。
SOFALite2 對外落地後,也計劃將它落回主站,所以就基於 SOFALite2 商業版新作了一個主站版,打通了主站的 LinkE 和 PaaS、九洲等內部研發運維體系,並更名為 SOFABoot。SOFABoot 2.x 主站版(基於 SpringBoot 1.x)也在 2017 年正式上線。
剛開始的時候 SOFABoot 商業版的能力還是比較簡單純粹的,但是在落地主站的時候,為了降低大家接入成本,兼容 SOFA4 的老的編程界面,並未設計全新的更簡潔的 API。另外 SOFA 時代眾多的二方包模塊等不得不將 SOFA 裡的上下文隔離能力也進行了移植(上下文隔離功能默認開,但可以關)。之前 SOFA 的健康檢查,日誌隔離等能力也進行了移植。而類隔離的能力,在 SOFABoot 裡則移植到了全新的 SOFAArk 框架,默認不開啟。
2018 年 4 月 SOFAStack 系列開源,SOFABoot 作為第一批開源項目, 在 v2.3.0 基礎上正式對外採取 OpenCore 的策略進行開源,SOFABoot 產品也分為了三個版本:開源版、商業版、主站版,在代碼結構上的關係就是商業版繼承開源版,主站版繼承商業版。

SOFABoot3 - 2018 (維護中)
2018 年 3 月 SrpingBoot 發佈 v2.0.0。
2018 年 9 月基於 SpringBoot 2.0.x 最新版發佈 SOFABoot 3.0.0 版本。2019 年 8 月 Spring Boot 1.x 停止維護,SOFABoot 2.x 也不再進行二位版本號更新。
2019 年 9 月 SOFABoot v3.2.0 參考 SpringBoot 進行了工程代碼結構重構,正式發佈。
同時在主站雲通未來 Serverless 戰場裡,基於 SOFABoot 和 SOFAArk 的模塊化發佈能力上線。全新的 SOFAArk 發佈模式可以將應用和模塊作為兩個獨立實體,在 LinkE 和 ServerlessPaaS 分別進行開發運維。SOFAArk 發佈模式很好的支持了各種業務中臺場景,做到了模塊(Function)級別的發佈和運維,讓業務模塊開發者徹底不用關係資源等問題。

現狀分析
截止 2020 年 6 月,目前各個框架使用情況:
SOFA3 應用:180 左右,版本集中在 3.4.3.23
SOFA4 應用:1800 左右,版本集中在 4.4.8.17 以上
SOFABoot 主站版應用:600 左右,版本集中在 2.6.16 和 3.3.1 以上
SOFABoot 商業版應用: 未完整統計,約 500+,版本非常分散,從 2.1.x 到 3.x 都有。
SOFABoot + SOFAArk 發佈模式:20+ 中臺應用

從 SOFA 歷史裡,可以看出開發框架的技術是一步步演進過來,技術方案都是為了滿足當時的業務場景所做的選擇。目前的框架存在非常多歷史遺留技術債,導致和微服務、雲原生的理念還是有比較大的差距的。這些都是表象的東西,其實導致這些的原因主要那就是兩大矛盾:
技術(業務)發展與技術債務的矛盾。隨著公司的不斷髮展,業務面臨的問題越來越複雜,業務量也越來越大,可以看到技術架構在不斷的發展,從第一代到現在的第五代架構,業務和技術都在不斷演進中。開發框架和中間件本身是為離業務最近的,都在屏蔽這些架構演進對業務應用造成的衝擊,這就導致中間件代碼裡有很多歷史債務(例如 XML 配置、WS 協議等等),框架產品的發展都必須揹著這些技術債務前行。另外框架產品本身是被全站應用所依賴的,任何的改動都會對全站應用造成影響,導致打破現狀(例如二方包的用法)去做突破很難,就算像 SOFABoot 體系打破了 SOFA 體系的一些設計,做了一套較新的框架,也不得不面臨全站上千個應用的平滑遷移的問題,因為遷移本身也要巨大的成本。
技術管控和技術自由的矛盾。對於一家中大型公司來說,開發人員眾多,技術水平也參差不齊。從研發效能來說希望開發框架統一版本的,這樣可以降低溝通協作成本,學一次就可以看懂公司的業務代碼;從運維角度,統一版本可以統一全站應用的發佈體系、運維體系、監控體系;從技術風險、安全等的角度,統一版本可以拉齊全站技術風險水位,包括希望大家用的組件、能力都是有限的可控的,這樣所有的業務代碼依賴的組件、能力都是可信的。而對研發同學本身可能就是另外一個角度了,我們的研發同學(特別是新同學)可能是來自不同的學習工作環境,他們有自己熟悉的技術棧,可能已經非常熟練的使用了社區開源的一些技術,當他們面臨一個強技術管控的內部開發框架時,肯定會基於已有的熟悉的知識體系去挑戰,發現一些無法滿足的功能、被“束縛”後的能力、“老舊”的研發體驗,就會覺得失去了技術的“選擇權”。特別是微服務、雲原生等新興思想的流行,在開源社區裡微服務框架更是層出不窮,跨語言解決方案也很多,選擇也越來越多,這就造成了管和被管的矛盾。

除此之外,開發框架本身也有很多使用體驗上的問題需要做優化,目前主要問題就集中在:
文檔、demo不夠完善
歷史技術債例如 Spring 上下文隔離,類隔離
編程界面太老,都是 XML 等,配置項混亂
應用啟動速度慢
日誌太分散,無統一規範,無統一錯誤碼
SOFA 遷移 SOFABoot 的成本進一步降低問題

上面這些問題都是我們未來要去解決的問題,參見爆效君的反饋帖。

雲原生下的開發框架
螞蟻在 2019 年雙十一實現了 Service Mesh 的核心應用全覆蓋,給開發框架帶來了更多的可能性。我們看到在 Service Mesh 模式下,RPC 相關的很多能力不再是業務同學所關心的,他們可以關注更少的細節,這些複雜的能力都可以被 Sidecar 所管控。除了 Service Mesh 外螞蟻也進行了更多的探索和落地,例如 Message Mesh、DB Mesh,我們慢慢的發現,或許這就是中間件的未來方向之一。
我們認為下一代開發框架應該是「重 Sidecar、輕框架」。
「重 SideCar」 是指我們會將更多的中間件能力下沉到 Sidecar 裡,並對上層提供一層標準的 API,我們的開發框架只需要對接 Sidecar 的這層 API 後再接入螞蟻技術體系的應用,就自動具備了螞蟻的技術風險、單元化等能力。對上層的能力越簡單,開發同學理解的複雜度越低,學習成本也低,效率就能提高。由於 SideCar 容器和應用容器可以分開運維,也能一定程度的提高啟動速度。
「輕框架」是指在滿足全站統一發布、運維、技術風險等管控的述求下將選擇權儘可能的還給我們的業務開發同學。首先開發框架還是需要有一定的統一管控的,例如健康檢查,Metrics,日誌輸出等,因為這些已經跟全站的基礎設施結合的比較緊密了。其次,目前的很多能力裡是有很多技術債的,我們希望這些能力都是可選且默認關閉的,讓我們框架更加的輕裝上陣。最後,我們希望會推各個中間件改造,例如更規範的日誌輸出,提供更加友好的全新 API 和 配置,讓我們的開發體驗更加接近原生的 SpringBoot。
由於大部分的技術風險、安全等能力都下沉到 SideCar,那上層的開發框架也可以有更多的選擇,不管是 SpringBoot 或者是 Nodejs,Golang 等跨語言的應用,只要技術棧對接了發佈運維體系,就可以作為大家日常的開發選擇。
3.png

進行中的事情
圍繞研發效率和用戶體驗,接下來我們會做如下事情:
中間件能力下沉: 基於 MOSN 打造下一代中間件,將更多的框架和中間件能力下沉到 sidecar,業務更少感知中間件。
啟動速度優化:優化 SOFA/SOFABoot 啟動速度,通過框架的優化、中間件組件優化和 Mesh 化,提高應用在本地開發測試和線上運行的啟動速度。
框架組件統一治理:基於 SOFABoot,拉齊中間件 Starter,依次完成依賴治理、統一 API、日誌梳理、配置梳理等等,同時完善已有的開發手冊、用戶手冊、demo 等,讓我們的開發體驗更加接近原生的 SpringBoot,降低開發學習成本。

這些事情有的體現在數字生活樣板間戰場和可信金控架構戰場裡,有的是單獨的專項治理。不管推進的方式有哪些,我們還是希望能讓我們的研發同學越少感知底層的基礎設施,降低開發框架的複雜度,提高開發框架的研發體驗,從而提高研發同學的研發效能。

歡迎大家持續關注。也歡迎感興趣的同學加入我們,一起打造下一代的中間件運行時。

Leave a Reply

Your email address will not be published. Required fields are marked *