隨行付微服務化的道與術

本分類文章,與「隨行付研究院」微信號文章同步,第一時間接收公衆號推送,請關注「隨行付研究院」公衆號。

微服務的目標是提高響應能力,降低複雜度,讓一切去中心化是微服務的最高宗旨。

背景

隨着研發團隊的項目工程的增加、代碼量的膨脹、團隊人員的增長,傳統的單體架構的弊端越來越凸顯,嚴重影響了業務的快速創新和敏捷交付。隨行付在2015年底爲了解決傳統單體架構面臨的挑戰,先後經歷了單體架構、系統模塊拆分以及到現在的微服務化。

微服務架構並非銀彈,它的實施過程中會面臨很多的陷阱和挑戰、幾乎影響到整個軟件開發的生命週期,稍有不慎,會導致整個微服務改造的效果大打折扣,甚至失敗。

本公衆號接下來的一段時間會協同隨行付架構部、隨行付技術委員會等技術團隊,結合隨行付的一些實際經驗,論證微服務架構實施的道與術。

微服務原因

爲什麼要做微服務化?可以從以下三個方面看爲什麼搞微服務。

  • 分而治之:減低複雜性
  • 分而用之:提高可重用性
  • 分而做之:提高開發效率

可以用變化的成本來衡量架構的好壞。而架構的目的是管理複雜性、易變性和不確定性,以確保系統在進化過程中,架構的變化不會對應用產生不必要的負面影響。保證業務和研發效率的敏捷、保證易變應用頻繁響應市場需求而中臺部分的影響儘可能的小。

10幾年前,一提到架構,大多數人都會認爲,架構=性能+高可用。隨着現在的技術不斷更新(Docker、人工智能、區塊鏈等技術)、各類開源軟件異軍突起、DevOps理念深得人心、敏捷開發成爲主流開發模式等等,性能和高可用已經不再是那麼棘手的問題。應用如何可持續發展?產品如何能快速上線/快速迭代?可維護性、可擴展性、成本,開始慢慢成爲很多架構師的關注點。而微服務架構的根本目的就是降低複雜性。

微服務前提

業務拆分

採納微服務架構首當其衝的問題就是根本沒有一個確定的、良好定義的算法可以完成服務的拆分工作。像軟件開發本身,服務的拆分和定義更像是一門藝術。更糟糕的是,如果你對系統的服務拆分出現了偏差,你很有可能會構建出一個「分佈式的單體應用」,一個包含了緊耦合服務的必須部署在一起的系統。這將會把單體架構和微服務架構兩者的弊端集於一身。

自動測試

微服務一個明顯的表象就是隨着服務的增多,如果繼續沿用傳統的測試模式就會遇到瓶頸,爲了保證高效的迭代,儘量做到測試自動化。通過自動化讓測試也可以「一處編寫,處處運行」、讓迴歸測試日常化。

自動運維

當互聯網發展到今天,業務要保持對市場變化的一個高效響應,自動化運維就是提升交付速度的一個重要環節。微服務拆分之後,每個服務都可以獨立部署,不再是固定的時間段去升級,人肉運維已經成了阻礙進步的絆腳石了。

多維度監控

硬件環境、服務狀態、系統健康度、服務調用情況、異常的實時告警以及生產事故的事先預警等等。監控在實施微服務過程中至關重要。

微服務架構原則

技術棧統一

一定要使用成熟技術,充分考慮新技術帶來的性價比。所謂成熟不僅僅是指有良好的社區活躍度、穩定性、節約開發成本、提高開發效率。更多的是指在隨行付的技術普適度,說白了就是有多少人會,出了問題有多少人能hold住。

數據最終一致性

權衡好哪些服務是最終一致、哪些必須是強一致。而強一致的保障機制是什麼?框架層和應用層相互互補來共同保障數據一致性。

服務無狀態

對於無狀態服務,首先說一下什麼是狀態。如果一個數據需要被多個服務共享,才能完成一筆交易,那麼這個數據被稱爲狀態。進而依賴這個「狀態」數據的服務被稱爲有狀態服務,反之稱爲無狀態服務。那麼這個無狀態服務原則並不是說在微服務架構裏就不允許存在狀態,表達的真實意思是要把有狀態的業務服務改變爲無狀態的計算類服務,那麼狀態數據也就相應的遷移到對應的「有狀態數據服務」中。

場景說明:例如我們以前在本地內存中建立的數據緩存、Session緩存,到現在的微服務架構中就應該把這些數據遷移到分佈式緩存中存儲,讓業務服務變成一個無狀態的節點。遷移後,就可以做到按需動態伸縮,微服務應用在運行時動態增刪節點,就不再需要考慮緩存數據如何同步的問題。

無狀態通信,我們推薦使用Restful通信風格,因爲他有很多好處:

  • 無狀態協議HTTP,具備先天優勢,擴展能力很強。
  • JSON報文序列化,輕量簡單,人與機器均可讀,學習成本低,搜索引擎友好。
  • 語言無關,各大熱門語言都提供成熟的Restful API框架,相對其他的一些RPC框架生態更完善。

AKF拆分原則

AKF擴展立方體,《架構即未來》一書中提出的可擴展模型。理論上按照這三個擴展模式,可以將一個單體系統,進行無限擴展。

X 軸 :是水平復制。比如講單體系統多運行幾個實例,做個集羣加負載均衡的模式。

Z 軸 :是數據分區,比如按照用戶請求的地區進行數據分區,北京、上海、四川等多建幾個集羣。

Y 軸 :是微服務的拆分模式,就是基於不同的業務進行拆分。

舉例:比如打車APP,一個集羣撐不住時,分了多個集羣,後來用戶激增還是不夠用。分析後發現打車APP上主要用戶是乘客和車主,就將打車應用拆成了三個乘客服務、車主服務、支付服務。三個服務的業務特點各不相同,獨立維護,各自都可以再次按需擴展。

服務拆分原則

單一職責

根據業務能力拆分。瞭解過面向對象的人應該都聽說過「單一職責原則」,即每一個類都擁有一個職責。比如一個搬磚類,它既可以蓋房子,也可以用來拍人,這時搬磚就擁有了兩個職責,所以我們應該把類拆分爲兩個。微服務也是一個道理,我們應該做到一個服務是用來做一件事情的。

鬆耦合、高內聚

緊密關聯的事物應該放在一起,每個服務是針對一個單一職責的業務能力的封裝,專注做好一件事情。(每次只有一個更改它的理由)。

DDD

領域驅動設計。我們怎麼按領域來劃分服務呢?對,我們可以按業務進行拆分,比如財務、訂單、倉庫等等。這樣我們的團隊也可以拆分開來分別負責不同的服務,這樣不僅項目清晰了,就連公司內部的組織結構權責分配也變得清晰了。

剛纔從橫向來看我們可以按業務領域拆分,縱向的呢?我們可以按層次進行拆分,比如最底層的數據層、基礎設施層以及與業務無關的推送、郵件、短信等等。我們還可以按安全性、性能等需要特別關照的以及通用的功能進行抽離沉澱。

掌握了領域驅動設計不僅遵守了高內聚、鬆耦合還符合了單一職責原則,那還不趕緊拆起來?

演進式拆分

避免過早拆分。過早的劃分服務,可能發展一段時間之後,服務的邊界會和之前有所不同,導致很多跨服務的修改,代價越來越高,最終又變成了單塊系統。所以一開始我們應該按照較粗的粒度進行劃分,而是否拆分爲更小的服務,應該由團隊組織結構決定,如果團隊對拆分後服務的維護成本更大了,那就應該放棄拆分更小的粒度。

服務開發原則

微服務的開發會面臨依賴滯後的問題。在單體架構時,大家需要什麼,往往喜歡自己寫什麼,這其實是沒有太嚴重的依賴問題。但是到了微服務時代,微服務是一個團隊或者一個小組提供的,這個時候一定沒有辦法在某一個時刻同時把所有的服務都提供出來,「需求實現滯後」是必然存在的。

例如:A要做一個商戶黑名單校驗,依賴服務提供者B。而B有其他更重要的任務,導致該服務的開發優先級排的比較低,無法滿足A的交付時間點。A會面臨要麼等待,要麼自己實現一個服務。

一個好的實踐策略就是接口先行,基於契約,語言中立。服務提供者和消費者解耦,並行開發,提升產能。無論有多少個服務,首先需要把接口識別和定義出來,然後雙方基於接口進行契約驅動開發,利用Mock服務提供者和消費者,互相解耦,並行開發,實現依賴解耦。

採用契約驅動開發,如果需求不穩定或者經常變化,就會面臨一個接口契約頻繁變更的問題。對於服務提供者,不能因爲擔心接口變更而遲遲不對外提供接口,對於消費者要擁抱變更,而不是抱怨和抵觸。要解決這個問題,一種比較好的實踐就是管理 + 技術雙管齊下:

  • 代碼通過Sonar掃描(隨行付Sonar中定製208條規則)

  • 有80%以上的單元測試複雜度

  • 允許接口變更,但是對變更的頻度要做嚴格管控

  • 提供全在線的API文檔服務(例如Swagger UI),將離線的API文檔轉成全在線、互動式的API文檔服務

  • API變更的主動通知機制,要讓所有消費該API的消費者能夠及時感知到API的變更

  • 契約驅動測試,用於對兼容性做迴歸測試

隨行付微服務平臺是以DevOps爲理念,基於Spring Boot、Spring Cloud、React、React Native、容器技術、人工智能等,面向微服務應用的PaaS平臺。實現基礎設施雲化、應用架構現代化和開發流程敏捷化。

平臺核心及功能介紹

Spring Cloud生態時序圖

如圖上所示,我們圍繞Spring Boot、Spring Cloud做了很多功能的擴展,讓Spring生態在隨行付能生長出更多的解決實際問題的「果實」,同樣並沒有盲目的造輪子。因文章篇幅,技術篇更多內容會在系列文章中着重介紹,會從各個中間件入手介紹隨行付金融科技技術生態。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章