轉摘-談談後端業務系統的微服務化改造

談談後端業務系統的微服務化改造

做者 張旭 發佈於 2016年4月29日 | 1 討論html

1. 篇首語

業務系統是任何一個用戶產品的必須組成,充當着一個門面的角色,用戶的輸入就是這個系統須要維護的,數據存取是整個系統的核心。例如,廣告業務系統的輸入是廣告主的投放約束、定向條件,微博業務系統的輸入是短文字、圖片等。前端

在應用發展初期或者規模不大的狀況下,有很是簡單的實現方案,LNMP、JSP、PyWeb都是你能隨口說出來的詞,若是用某種架構方式來描述,那就能夠稱作單體模式(Monolithic,Martin Flower大神所提出的,後面還會介紹),而這些技術都是單體模式的成熟解決方案,它們可使你工做在「應用層」的最頂端,各類中間件、框架能讓你省心地幹好業務,開發人員能夠經過「模塊化」的手段來管理業務系統的複雜度,使他們之間解耦、複用。簡單來講,這個單體就是以下這種層次劃分。git

表示層       前端(HTML+CSS+JS)                        
  |             |
邏輯層     業務系統(PHP、Java、Python是經常使用的語言)         
  |             |                               
數據層      數據庫(MySQL)    

看起來很簡單,對吧。誠然,業務系統在這裏面還須要作不少,好比緩存、SQL優化、數據分區、系統安全工做,固然還有對於代碼的維護和重構。這種工做方式能夠很好的工做幾年、甚至十年,可是若是業務發展很是快,在系統複雜度、業務規模、參與人數、代碼腐化程度都不斷上升的狀況下,你會發現整個項目正陷於泥潭,PM/RD/QA/OP常常抱怨:github

"改個小功能,怎麼要拉這麼多模塊?"web

"拉模塊也就罷了,改的地方多,編譯太慢了。"數據庫

"慢也就算了,關鍵不知道怎麼改,這代碼太醜陋了,算了,爲了知足PM的排期須要,湊合來吧。"編程

"湊合來了,QA發現bug,返工再返工,延期再延期。"canvas

"上線了,oh my god,報case了,性能有問題,原來是依賴的模塊訪問數據庫用了for循環select。"後端

透過現象看本質,我總結了來看就這三點問題:設計模式

一、業務邏輯複雜耦合,開發維護成本高。

系統複雜度、規模、參與人數都和腐化程度成正比,單純的靠模塊化,後期來看會存在個別模塊成爲」大怪物「,臃腫不堪,粒度過粗,難以複用。

二、交付效率和質量低。

在敏捷和持續集成方法論、實踐大行其道的現今,迭代的定期交付率、單測覆蓋率都不盡如人意,線上問題頻發。

三、非功能需求不達標。

非功能需求指標特指性能、可用性、可擴展性等方面,代碼的腐化和缺乏維護、重構,以及沒有代碼潔癖的人污染下,必然致使性能逐漸降低,甚至出現不一樣資源競爭的短板效應,形成整個系統crash,同時一個大怪物的伸縮性較差,不能隨意橫向擴展某個細分功能點。

我想任何人作架構都須要秉承「業務需求決定技術演化路線」的思路,那麼這些暴露出來的現狀和問題都驅動系統去轉型,在系統和人之間找到一種最佳的合做模式,匹配已有的生產力和生成關係。正如軟件開發學泰斗Kent Beck所說的:

「Design is there to enable you to keep changing the software easily in the long term」 ,即「變化發生時設計被破壞的程度」

 

放眼業界,面對複雜的、大規模的、多人協做完成的業務系統,如何管理好這個複雜度,有不少方法,模塊化、OSGI、傳統服務化SOA等等,當今最佳實踐的趨勢仍是服務化,而微服務是最近火熱起來的概念,有些人確定以爲這不就是炒做嘛,可是無論黑貓白貓能抓耗子就是好貓,因此解決問題是重點,不要刻意去批評一些名字,那麼本文要重點介紹的就是——如何作微服務化轉型和改造。

在接下來說以前,要重點聲明,本文並非推崇服務化,不鼓勵單體模式,相反而是至關確定和支持單體模式,它模塊依賴簡單、一個發佈包、部署於一個容器都使得構建應用很是的簡單,在體量還不大的狀況下,首先應該解決的是搭建好一套絕對穩定的基於模塊化的平臺,待體量逐漸長大,再去根據實際須要進行拆分,團隊也隨之變化(facebook的單體持續了很是長的時間,一是人員素質高,二就是基礎平臺建設的很是好)。再下個階段體量大到飽受單體模式之苦,也應該先建設平臺化服務,建設好以後,先按照大的粒度進行拆分,逐步再微服務化,不然,直接上服務化、甚至下面要說的微服務都是很是危險的,鮮有成功案例。

2. 微服務化改造

作改造通常要經歷三個步驟:

第1、技術選型決策

第2、架構設計規劃

第3、落地實施應用。

下面依次展開三個部分,重點介紹前兩個步驟,有了這兩個,落地應用也就順水推舟的好作了。

2.1 技術選型決策

2.1.1 選擇微服務化方式

選擇服務化,衆所周知就是SOA嘛,這是一種架構風格,重點在原則、理念、方法論等高思惟層次上,對於工具、框架、解決方案沒有作強制限制,ESB、websercie(基於WSDL和SOAP/BPEL)這兩種是企業中流行的,也是過去一直引領SOA的技術領頭羊,可是隨着互聯網應用的發展,在敏捷快速迭代、高可用、高性能、高併發等方面要求愈來愈高,傳統的SOA並不適合這種場景。那麼,如今的互聯網流行的實現方式是什麼呢?一種最佳的實踐方式就是微服務化(Micro Service)。

[配圖1]

微服務就是一種SOA的實現方式而已,更加側重於在服務的細分演化,是指引服務的具體落地方案層面的一種實踐方式。過去不少互聯網公司在實踐,你能夠把淘寶的dubbo、HSF,navi-rpc服務化框架看作比傳統SOA更適用、更貼近微服務化實現的服務化框架,依賴這些框架能夠方便的作服務化。這個趨勢被Martin Flower大神所發現,而且提出了,大家這些不都是在作「微服務」嘛。

Martin對微服務這個術語(terminology)的解釋是:

In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.

簡而言之,微服務化就是以一系列小的服務來開發支撐一個應用的方法論,服務獨立在本身的進程中,經過輕量級通訊機制交互(一般是走HTTP協議)。這些服務是圍繞着業務上的組織結構來構建的,全自動的、獨立部署。幾乎看不到中心化的服務管理基礎設施,可使用不一樣的編程語言和數據存儲技術來實現不一樣的服務。

在簡單的一種理解來自於一本書《Building Microservices》(Sam Newman, O’Reilly Media),Microservices are small, autonomous services that work together. 微服務化就是一堆小而自治的服務,讓他們一塊兒工做起來。

相比於傳統的SOA,Martin的總結特色能夠參考他的博客還有視頻(Youtube連接),一共是9個特色,這裏不想贅述,而是說說我我的的理解,微服務化的特色在於:

一、模塊即服務

微服務中的組件在邏輯或者物理層次更趨於細分,這個細分不是極致的,而是一種粒度適中的選擇,一般這些組件在前期能夠是一些模塊,可是當須要時,例如業務上須要拆分獨立,或者非功能需求上須要擴容等,均可以靈活的拆解出來。這個特色很是重要,由於業務系統中模塊化實踐,隨着軟件規模的變大,很容易繞過障礙而使得不一樣模塊耦合、依賴關係複雜,這種紀律性很難保證,從而削弱模塊化的結構、下降了團隊的生產力(敏捷開發和持續交付愈來愈難作,部署起來太龐大了你們的開發士氣不高,並且痛苦),很快的這個模塊就會變成一個大雜燴,而服務能夠作到自然的壁壘,僅僅經過交換契約(一般是API或者proto)來作交互,這是一個演化的過程,不只有利於分而治之,到達複用的目的,同時老系統也能夠灰度的改造剝離。

二、獨立自治

這意味着服務是獨立開發,獨立測試,獨立發佈,獨立部署,獨立運維的,某個細分團隊負責整個生命週期管理,這就是」康威定律(Conway’s law)」的通俗解釋,官方解釋是「一個組織的設計成果,其結構每每對應於這個組織中的溝通結構」,服務的規劃不就是多人、跨團隊協做的溝通模式嘛。好處在於摒棄原來的火車模型(全部模塊一塊兒發佈部署),擁抱獨立快跑,這也更好的支持了敏捷和持續集成的方法實踐。同時去除了牽一髮而動全身的問題,單一職責的來進行修改需求或者重構一個點,開發和構建方便,不影響整個產品的功能,一個bug不會crash掉整個產品,針對不一樣的類型,區分計算密集型仍是I/O密集型,區分業務上更好使用關係型仍是NoSQL,區分2/8原則、即80%常常修改的服務獨立出來自成一家,區分短板功能、針對瓶頸能夠作水平擴展、避免資源競爭,甚至能夠區分技術棧、突破語言限制。最後,這也是和第一點遙相呼應的,獨立的服務能夠實現很是大程度上的複用,服務之間依賴輕量級的接口,而不是模塊。

三、去中心化的數據管理

在單體模式中,一個應用面對一套數據庫,數據庫能夠按照物理拆分,進行shard分區,或者按照邏輯庫隔離,不一樣的業務路由到不一樣的庫,同時作一主多從等結構上的設計,這些原則在微服務中仍然適用,只不過微服務在服務拆分的同時,也須要將數據庫分離,獨立的服務維護獨立的數據庫,這對數據庫也是減負,同時技術選型、SLA保證都會區分開來,把精力留給那些重要的業務數據庫,進行分級的對待,而不能像之前同樣一視同仁,一個不重要的邏輯庫的bad SQL慢查詢,阻塞了其餘正常的查詢,這是徹底能夠避免的。

四、輕量級的通訊協議

傳統的SOA使用ESB或者Webservice這種重量級的解決方案,微服務推薦使用一些更輕的解決方案,要通用性,能夠用Restful架構,走HTTP通道,支持Json序列化協議;要高性能,能夠考慮一些高性能的I/O模型,例如epoll、Actor等,能夠直接走tcp通道,使用protobuf序列化協議,同時保持長鏈接(這裏有一個例子Navi-pbrpc就是一個這樣的具體落地框架);要異步,用可靠持久的RabbitMQ或者高性能的ZeroMQ來作P2P、Pub/Sub、廣播broadcast消息通訊。而這種輕量級還須要體如今代碼調用中,模塊化直接經過函數、方法調用便可,服務化後能不能在API層面作到無侵入,無縫的切換、簡單配置,這些都是服務化框架要支持的。

五、爲失敗設計

服務化調用從進程內in-process的調用,轉變爲跨進程的分佈式調用,這種由分佈式特性引發的自然不可靠性,須要變爲相對可控。也就是服務間的通訊要假設不會成功,爲失敗處理。異常的傳遞,可否透過RPC,在調用方本地還原,就像函數、方法調用同樣?一個點、或者服務的處理錯誤率到了一個閾值,爲了避免影響整個產品,要作錯誤隔離,能夠考慮熔斷(circut break)、艙壁隔離模式、限流、回退等手段,最後還有一個冪等性問題,重試的調用會不會對業務形成影響,這個要具體問題具體分析了。

六、基礎交付設施自動化

這個特色是整個微服務中的最大亮點,包括持續集成CI、持續交付CD和PaaS平臺的結合。微服務在細分的背景下,在project結構,物理結構上都提升了一個複雜度,若是還要作到提升軟件交付鏈路的總體效率,就須要在基礎交付上作一個大的轉變,所以DevOps文化,讓每一個人都參與交付,在規範的流程和標準的交付(例如,標準的容器)下,同時在PaaS服務提供商的幫助下,完成一個服務的自動部署發佈。

任何事情都是兩面的,有好的優勢,固然會存在弊端,微服務的缺點個人理解以下:

  1. 分佈式調用形成的性能、延遲問題。(能夠採起的措施包括粒度適中、批量、高性能RPC、異步通訊等)
  2. 可靠性很差保證。(剛纔提到的爲失敗設計能夠解決)
  3. 數據一致性難以保證。(看各自的業務,確保最終一致性便可,實際上大多數互聯網產品不多不用事務;可是我目前所工做的商業產品領域,是須要事務的,除了不推薦的兩段式提交,還能夠引入仲裁者、補償措施來解決分佈式事務問題,問題能夠單獨開一篇文章介紹了,這裏就不展開了)
  4. 總體複雜度提高。服務多、依賴多、調用多、契約如何管理、監控如何作,調用鏈上怎麼肯定哪一個點有問題,服務的SLA保障、性能、錯誤率、告警、這麼多服務如何集成測試、交付容器如何上線等等問題。(經過服務治理能夠有效下降微服務化複雜形成的低效,轉爲推進工程生產力的高效進化,同時基礎交付設施的自動化能夠加速研發效率,選擇了微服務就等於選擇了成本優先戰略,投入的成本都是爲了將來業務的更好發展,避免J-curve曲線式的研發模式,只有在體量大,基礎設施包括服務化框架、治理能力完善的基礎上,加上流程、規範以及工具和技能的輔助下,才能夠真正發揮服務化的威力,不然只有自討苦吃)

2.1.2 微服務化框架和治理模型

架構方式、原則達成了共識,你再往下看。虛的說完了來點乾貨,來介紹下我所在team實踐的微服務化,最核心的就是微服務化框架,業界流行的阿里的框架dubbo以及淘寶內部的HSF,Navi-rpc均可以看作微服務化框架的雛形,加上服務治理中心的管理、基礎交付設施的保障就能夠構成完整的一套微服務框架。咱們的框架(暫時僅內部使用)總體架構以下圖,他由服務發佈者、調用者和治理中心三者組成,屬於標準的協調者模式。

[配圖2]

(點擊放大圖像)

生產者中服務邏輯在Spring或者Guice等IoC框架的bean中,由IoC容器託管,爲了符合模塊即服務的思想,在框架層級實現了一套可插拔組件的引擎,去實現組件的掃描,須要暴露服務的發佈出來,依賴別的服務的,經過字節碼技術生成Rpc調用代理Stub,造成了一個基於組件的容器,經過JSR315這個規範的SPI實現對接到J2EE容器,下面的消費者結構相同。

在服務啓動後,首先會第一步註冊本身到服務治理中心,上傳本身的契約、版本上去,治理中心若是經過檢查就發佈出去,以後和治理中心經過長鏈接協議(咱們採用websocket,由於現成、簡單)作一個訂閱發佈的通道,能夠供收集狀態,推送服務Endpint的變動;服務消費者能夠去治理中心或者Maven倉庫獲取契約、SDK,治理中心推送Endpoint下來,供路由進行Rpc調用,經過消費者也經過長鏈接協議來進行狀態和統計信息的上報,供治理中心進行分析決策和反饋。

服務治理中心爲了保證高可用性,一般使用Zookeeper這個流行的開源的基於Paxos的方案,固然最近漸漸流行起來的kebernetes的etcd是基於Raft的集羣共享數據、也能夠作服務的發現的解決方案。

隨着這種分佈式調用愈來愈頻繁,就須要服務治理能力愈來愈強,不然就是一張混亂的、無序的Rpc調用的網,沒法管理複雜度。

這裏創建了服務治理的模型,在下圖中的服務治理中心來實現,模型從這樣幾個角度來考慮如何治理服務,包括通訊、契約、版本、監控、安全、交付等角度,依託服務治理中心,有了這套基礎設施保駕護航,服務化就能夠真正作到提升研發效率、提供優雅的開發體驗。

[配圖3]

(點擊放大圖像)

在基礎交付設施自動化上,以下圖所示,體如今自動化、容器化交付這個流程中,在平臺化的背景下把團隊思惟轉換爲DevOps式的,依託Docker和k8s完成了PaaS平臺的對接,同時和QA一塊兒協做完成持續交付流程的創建。

[配圖4]

(點擊放大圖像)

2.2 架構設計規劃

這裏所指的架構,特指組織、服務的架構設計,非部署和代碼架構。

下面我要介紹的,都是扣題,是已有系統的服務化改造,是一個已經存在的、複雜的、體量大的業務系統。

作架構設計規劃,主要分爲步驟:

  • 1總體架構設計
  • 2業務領域抽象、建模
  • 3服務規劃與層次劃分
  • 4服務內流程、數據、契約(接口)定義和技術選型。

這裏主要介紹前三個步驟,第四個偏向於個例,同時須要強結合業務需求、特色分析解決,這裏不作詳細展開。

2.2.1 總體架構設計

還記得文章開說所說的單體模型嗎?在一個複雜的、規模大的業務系統中,使用微服務化方式實現,就須要從上到下的來作總體架構,下面這張圖是我所在的商業產品的業務端到檢索端的架構圖。

[配圖5]

(點擊放大圖像)

共分爲5個層次。

第一層,模塊化組裝,是各個投放產品的門面,各個投放產品能夠經過搭積木式的方式,組裝下層服務,就能夠完成一個面向用戶的功能,最多見的SpringMVC技術、Java設計模式中的facade模式就屬於應用到這一層的一些點。

第二層,計算服務層,服務化也就是在這個層次上展開的,每個小圓圈都是一個微服務,這是整個服務化的核心,各個服務圈出來的都是一個個服務簇,好比投放管理一個簇,報告報表一個簇。

第三層,數據存儲層,會針對各個業務拆分,按照物理庫或者邏輯庫進行隔離。

第四層,廣告傳輸層,將多shard的MySQL寫入的廣告增量實時傳輸到檢索端,造成一條增量流(incremental data stream),咱們經過模擬爲MySQL的一個從庫來捕獲解析binlog實現,將binlog增量映射爲語言級別的抽象類型,供下游使用,下面一層就是一個數據接收方,其餘的還包括一些MQ訂閱方(如導入kafka、RMQ、ZeorMQ等),HDFS存儲等,這樣就造成了業務系統的數據快速、高效、實時傳輸的目的。

第五層,檢索端。是廣告投放系統的核心,根據媒體環境、用戶特徵匹配最佳的廣告,進行創意的投放,你所看到了圖片、H五、flash廣告都是這套系統響應的,能夠作到千人前面,最佳化廣告主ROI與用戶體驗的折衷。

2.2.2 業務領域抽象建模

技術是爲業務服務的,沒有了業務,純粹的講技術都是紙上談兵,解決問題是全部技術的出發點,微服務化也不例外。服務於業務,就須要對業務有深入的理解,技術才能造成良好的輸出。

有了前一步的總體架構規劃,下一步就是計算服務層中的微服務如何規劃的問題,這部分最爲複雜,須要深刻到產品業務中。拍腦殼規劃固然能夠,這叫作經驗直覺主義,我認爲經驗主義缺乏規範化的表達和標準化的設計,面對將來的修改需求,其架構的生命力不會很強。所應該站在更高的視角上嘗試解決,首先就是要規範化需求表達,下圖就是一個投放實施的表達,使用巴克斯範式(BNF範式)表達,將投放實施分爲受衆、媒體、場景等定向的選擇,每種定向又分爲多個約束條件,逐層深刻,這個規範是全部已有產品的萃取,在新產品的打造中須要遵照的,通常會和產品經理一塊兒打造。

[配圖6]

(點擊放大圖像)

而後各個投放產品進行的功能矩陣劃分的標準化設計,以這些爲基礎,就能夠有理有據的進行服務規劃,抽象分解出來的服務域高內聚,職責很是清晰,服務內的實體也是建模的,以下圖所示,每一個包都是一個微服務。

[配圖7]

(點擊放大圖像)

2.2.3 服務規劃與層次劃分

基於對業務的抽象分解,在計算服務層內部,就能夠進行更加細分的層次規劃,先是垂直拆分爲展示層、計算層、數據資源3大縱層,核心的計算層又細分爲3個層次,包括業務流程處理層,經過組裝下層服務完成功能;業務邏輯組件是自包含,跨產品線、高度複用的組件;下面公共服務組件是一些通用服務。而後水平劃分爲多個服務簇。以下圖所示。

[配圖8]

(點擊放大圖像)

按照以前的服務規劃,將各個微服務安置其中,最上層的web-ui和api服務負責和前端js以及客戶端(安卓或者iOS)API打交道,中間例如推廣管理做爲一個業務流程處理組件的workflow,能夠調用下面的微服務進行組織,完成一個投放流程的業務場景。全部這些服務都是經過分佈式服務化框架來進行通訊、治理的。

2.3 落地實施應用

下面是一個已有產品改造的案例,好比一個報表服務簇,過去是一個大單體,如今按照服務化的架構,進行拆分,最爲核心的就是中間這個sync-report服務,它從olap engine中查詢數據,而後經過merge字面數據,提供排序,過濾,分頁功能。圍繞sync-report抽取了多個不一樣維度的緩存,保證了核心報表服務的高性能,同時上層,無論是web-ui仍是api,都複用sync-report,這樣上層就會很薄,不用再管那些複雜的查詢邏輯,sync-report做爲標準、規範的技術解決方案,作到了統一複用與專職專用,加速了研發效率和交付。

[配圖9]

(點擊放大圖像)

3. 篇後語

本文所提倡的微服務,是結合做者所在team自身業務特色來講的,適合自身的場景,是創建在團隊人員素質到了,有成熟的基礎設施和框架、中間件輔助,流程也規範,包括CI、敏捷等,團隊都作好了準確去作這個轉變,有足夠的能力來實施,微服務化也就是水到渠成的事了。相反,小團隊在前期或者野蠻生長時期,不宜選擇微服務,不但影響效率還帶來額外的複雜度。成長型或者大公司,有成熟的流程、規範、基礎設施、平臺等,要想在整條交付鏈路上加速,就須要投入更多的資源保障微服務化,一切自動化了,能治理了,回頭看來這一切就都是值得的,遠期收益很是可觀。

最後要說的是,架構只是標準、骨骼,對微服務的討論不該該讓咱們忘記了更重要的問題,驅動軟件項目成功和失敗的重要因素。軟因素如團隊中人的素質,以及他們如何彼此合做、溝通,這都會對是否使用微服務有很大的影響。在純技術層面上來說,應該把重點放在乾淨的代碼、完善到位的測試,並持續關注架構的演化進步,這纔是一個軟件工程師的根本職責。

相關文章
相關標籤/搜索