有贊服務化架構演進
路,只有走過才懂;人生的酸甜苦辣,只有嘗過才明白;服務化,只有經歷過才能領悟。
服務化是網際網路公司成長的必經之路。隨著微服務的興起,很多公司如火如荼的搞起了自己的服務化,有興奮有無奈。那服務化該怎麼做,該做什麼?本文試圖從有讚的發展歷程來體會服務化發展。
有贊史
有贊成立於2012年11月,成立初期以社群電商產品為核心,2015年實現商業化,快速發展為一家2000+人的2B Saas服務公司,以電商平臺(微商城)和新零售(有贊零售、有讚美業、有贊餐飲)為主要發展方向。技術總是隨著業務的繁榮不斷演進,從一個差點死掉的初創公司到如今創造的電商+新零售生態,有贊經歷了從單體應用到服務化較為成熟演進過程。

有贊史.png
從時間跨度上我們可以將其發展大致分為四個階段:單體應用時期(2013-2015)、服務化初期(2015-2016)、服務化發展(2016-2017),服務化成熟(2017-至今)。
公司創立初期,選擇PHP作為核心開發語言,因為其開發速度快,試錯成本低。這也是很多創業團隊的選擇。一旦業務成型,使用者體量變大,開發團隊擴張,圍繞PHP開發的問題便逐漸暴露,如專案過於龐大、難以維護,釋出影響面大、開發效率低等問題。
為了解決這些問題,2015年公司開始進行服務化拆分,首先是縱向拆分,將核心的功能從iron(核心的PHP應用)裡面拆出來,如使用者中心、店鋪中心、商品中心等,服務化應用採用java開發。服務拆分後,首先需要解決的便是服務間呼叫問題,隨著新技術語言的引入,以及有贊雲業務的發展,跨語言呼叫的問題也日益突出。如何解決服務化的這些問題呢?下面詳細分析有讚的服務化之路。
單體應用時代
為什麼開始不把業務拆分好呢?可能有人會有這樣的疑惑。就企業而言,追求的是快速底成本驗證產品想法並佔領市場,進行低成本試錯;就開發而言,業務的發展是未知的,過度設計的架構可能會適得其反。有贊從一開始的月餅、代付、送禮等社交營銷玩法做到Saas級電商平臺,這一路的發展有不少心酸。
在早期,公司的系統架構圖如下圖所示,核心展示層、業務層都在強耦合在iron應用之中。談到iron,不知曾讓多少有贊人淚崩。“程式碼又衝突了!?”,“釋出又翻車了!”,“服務又回滾!?”。沒錯,這就是iron。

iron.jpg
iron是有讚的核心PHP應用,最初幾乎承載著所有的核心業務。目前iron在gitlib上已經有18G+之大,當有一批新同事進來時,如果有多人全量clone(不指定depth)很容易導致gitlib伺服器宕機,因此目前clone iron必須指定depth。
為什麼iron發展到這麼大?為什麼不早點拆分呢?主要是因為有贊初期的業務快速發展導致。在拆分老應用時,要保證新功能的快速迭代,對於一個高速發展的創業型公司,在那個歷史階段沒有足夠的資源與時間去遷移。所以iron的龐大似乎有著歷史的必然性。
隨著業務的快速增長和研發團隊的不斷擴張,單體應用的弊端不斷暴露出來。如團隊協作成本增加,開發、測試、部署不同模組相互耦合,導致系統穩定性下降等。在此背景下,服務化拆分,箭在弦上。

單體應用問題.jpg
服務化初期
Iron拆分
2015年7月,公司決心啟動了“乾坤大挪移”專案。核心目標是便是拆分iron,將核心業務從PHP向Java遷移,並逐步建立完善的服務治理體系,邁向了服務化的第一步。

iron拆分.jpg
“乾坤大挪移”專案的啟動,標誌著有贊正式進入服務化階段。服務化拆分第一個要解決的就是服務呼叫的問題,且一開始就遇到了跨語言呼叫的問題。最初的服務化呼叫方案如下,Java服務之間呼叫採用Dubbo協議,PHP與Java服務之間呼叫採用http協議。然而在該模式下存在不少問題,如Java服務開發者需要維護兩套不同的介面,增加了額外的工作量,並不友好;PHP無法支援長連結,會有大量的時間耗費在建立連結上,並且大量的短連結對於後端服務來說也是很大的負擔。

服務化初期.jpg
服務化發展
Nova興衰
隨著服務的拆分,公司需要一套跨語言呼叫的解決方案,於是Nova興起。Nova是基於thrift協議而制定的有贊RPC協議。通過這個協議,解決公司跨語言互動的問題,從而形成公司的Nova框架。從狹義來講,Nova是一種私有的通訊協議;從廣義來講是有贊SOA架構。對Dubbo、Zan-PHP進行擴充套件,支援新的Nova協議。

nova.png
Nova似乎解決了跨語言的問題,但卻存很多痛點:
第一,需要生成Thrift IDL,過程繁瑣,可讀性差,開發接受度不高;
第二,入侵性強,擴充套件性差,須深度定製;
第三,維護成本高,需要專門的團隊保障;
除此之外,還有一個原因是公司Java服務化的發展使Java成為核心開發語言(Java開發人員相對來說,在市場上是最好招的)。使用Nova有一定的接入和學習成本,且開發人員水平不一,在Java盛行的時期,Nova逐漸變得累贅。
由於這些痛點,導致Nova的好景不長,一直被開發人員詬病,全面推動困難。因此在這個時期,出現了Dubbo和Nova協議共存的狀態,Java內部採用Dubbo協議,跨語言採用Nova協議。回頭來看,Nova似乎成為了歷史性的過渡協議。
Tether萌芽
由於公司最初是已PHP為核心開發,業務系統還存在不少PHP應用,而PHP的多程序執行方式會帶來許多問題。比如無法支援長連結,會有大量的時間耗費在建立連結上,解決後端服務頻繁建立連結帶來的損耗,並且大量的短連結對於後端服務來說也是很大的負擔。未了解決這一問題,公司開始研發Tether。Tether主要實現了以下幾大特性:
1.支援以長連結方式進行信令透傳;
2.支援負載均衡,如輪詢策略;
3.支援服務發現,與name_service對接;
4.支援多協議解析(nova、http等);
Tether作為PHP的長連結解決方案,獨立部署在伺服器上,與應用解耦,由運維統一部署管理,為後續的Sidecar發展奠定了基礎。

tether.png
服務化成熟
Sidecar
隨著應用拆分的不斷推進,有贊已從原來的PHP開發模式,形成了Node.js + Java的開發模式,逐步去Zan-PHP框架。並且隨著電商雲業務的發展,越來越多其他語言的需要接入,此過程需要解決的核心問題是:Node.js等其他語言如何呼叫Java服務?

nodejs.jpg
有贊之前的跨語言使用的是Nova協議。然而在Nova一直遭詬病的背景下,如何更友好的解決這一問題呢?首先對比一下Nova協議與Dubbo協議:
Dubbo | Nova | |
---|---|---|
開發語言 | Java | 跨語言 |
序列化 | hessian | thrift RPC呼叫協議二次封裝 |
友好度 | 不需要IDL,更自然 | 需要IDL,接受度低 |
既然大家都習慣使用Dubbo,能不能在Dubbo的基礎上實現跨語言互動呢?
答案是可以的。為了建立更友好的跨語言服務化方案,Tether再次升級。實現了對Dubbo原生協議的解析與轉換,支援通過Http協議呼叫Dubbo服務。這次協議轉化的能力升級,也意味著Tether正式成為Sidecar元件。

tether.png
新協議設計
這種相容性協議轉換似乎解決了跨語言服務呼叫的問題,然而真正的跨語言需要有靈活高效的通用協議基礎。最近Dubbo官方也一直在推動跨語言程序。其核心的難點便是協議。Dubbo協議是私有的,其服務介面都是通過Java Interface描述,其涉及的傳輸模型DTO也是Java POJO定義,要想成為跨語言的協議標準有一定難度。並且由於Dubbo的Attachment欄位在尾部,Sidecar很難解析處理。而Sidecar形態需要面向多語言,協議問題首當其衝。通過Dubbo真正實現跨語言,新協議的設計是未來的關鍵。

dubbo協議.png
有讚的新協議設計目標如下:
1.多語言支援
電商雲的客戶可能使用多種語言進行開發,協議必須能夠支援各種語言無痛、方便的接入。
2.便於解析的請求header
為提供豐富和完善的服務治理功能,便於Sidecar解析和新增資訊的RPC請求header是必不可少的。
3.不改變內部業務的使用方式
有贊內部業務已經習慣了不編寫IDL,直接開發微服務介面的開發方式。新的協議不能改變內部業務的開發方式和開發習慣,協議上的升級必須是業務完全無感知的。
4.方便的相容和適配
推動業務升級是一個漫長的過程,新協議必須能夠支援Sidecar自動進行新、舊協議的適配和轉換,保證新舊版本協議長時間並存情況下的穩定性。
5.非同步支援和高效能
當前dubbo使用的RPC協議通過連結內唯一的request ID實現了非同步呼叫和consumer端的連結複用。新協議應當具備不亞於當前協議的效能,且必須具備支援非同步呼叫和連結複用的能力。
6.使用規範通用的RPC協議
為降低框架的複雜度和學習成本,方便後續接入和使用通用的開源元件,同時保證框架處於規範的生態中,儘量借鑑和使用通用的協議和系列化方式,減少自己設計和開發帶來的風險。
7.實現簡單
為降低使用新協議帶來的風險,新版協議應當避免複雜的實現,Java框架僅需經過簡單的改造或增加拓展即可實現,減少實現複雜序列化協議帶來的風險。
經過綜合考慮,有讚的新rpc協議將以HTTP/2為基礎,參考grpc協議。併兼容老的dubbo協議,保證協議的通用性和可拓展性。
總結
如開篇所說,“服務化,只有經歷過才能領悟“。作者遺憾沒有完整經歷過這些發展,本文主要參閱了很多歷史文件,試圖從過來人的角度簡述有讚的服務化發展歷程。本文描述的服務化主要在於服務呼叫問題上,而完整的服務化體系遠不止如此,核心至少還包括服務註冊與發現、服務監控、服務追蹤、服務治理等方面,這些方面,有贊也付出了很多的努力。
現在的歲月靜好,是因為有人替你負重前行。如今有讚的服務化體系已經比較完善,但也依然面臨挑戰。希望日後能在有讚的工作、學習、經歷中更好的成長。本文不足之處,還望指出。