致傳統企業朋友:不夠痛就別微服務,有坑

技術瑣話發表於2018-12-19

編者:把微服務講的接地氣的最佳作品。

一、微服務落地是一個複雜問題,牽扯到IT架構,應用架構,組織架構多個方面

在多家傳統行業的企業走訪和落地了微服務之後,發現落地微服務是一個非常複雜的問題,甚至都不完全是技術問題。

當時想微服務既然是改造應用,做微服務治理,類似註冊,發現,熔斷,限流,降級等,當然應該從應用開發組切入,一般一開始聊的會比較開心,從單體架構,到SOA,再到微服務架構,從Dubbo聊到SpringCloud,但是必然會涉及到微服務的釋出和運維問題,涉及到DevOps和容器層,這些都不在開發組的控制範圍內,一旦拉進運維組,對於容器的接受程度就成了一個問題,和傳統物理機,虛擬機器的差別,會帶來什麼風險等等等等,尤其是容器絕對不是輕量級的虛擬化這件事情,就不是一時半會兒能說的明白的。更何況就算說明白了,還有線上應用容器,一旦出了事情,誰背鍋的問題,容器往往會導致應用層和基礎設施層界限模糊,這使得背鍋雙方都會猶豫不決。

致傳統企業朋友:不夠痛就別微服務,有坑

有的企業的微服務化是運維部門發起的,運維部門已經意識到了各種各樣不統一的應用給運維帶來的苦,也樂意接受容器的運維模式,這就涉及到容器直接的服務發現是否應該運維在容器層搞定,還是應用應該自己搞定的問題,還涉及Dockerfile到底是開發寫還是運維寫的問題。一旦容器化的過程中,開發不配合,運維單方面去做這個事情,是徒增煩惱卻收益有限的。

下圖是微服務實施的過程中涉及到的層次,具體的描述參考文章雲架構師進階攻略

    致傳統企業朋友:不夠痛就別微服務,有坑      

在一些相對先進的企業,會在運維組和開發組之間,有個中介軟體組,或者叫做架構組,來負責推動微服務化改造的事情,架構組就既需要負責勸說業務開發實施微服務化,也要勸說運維組實施容器化,如果架構組的權威性不足,推動往往也會比較困難。

所以微服務,容器,DevOps的推動,不單單是一個技術問題,更是一個組織問題,在推動微服務的過程中,更加能夠感覺到康威定律的作用,需要更高層次技術總監或者CIO的介入,方能夠推動微服務的落地。

然而到了CIO層,在很多企業又體會不到技術層面的痛點了,而更加關注業務的層面了,只要業務能賺錢,架構的痛,中介軟體的痛,運維的痛,高層不是非常能夠感知,也就體會不到微服務,容器化的技術優勢了,而微服務和容器化對於業務的優勢,很多廠家在說,能夠說到表面,說不到心裡。

因而微服務和容器化的改造,更加容易發生在一個扁平化的組織裡面,由一個能夠體會到基層技術細節的痛的CIO,高瞻遠矚的推動這件事情。這也是為什麼微服務的落地一般率先落地在網際網路公司,因為網際網路公司的組織架構實在太平臺,哪怕是高層,也離一線非常的近,瞭解一線的痛。

然而在傳統行業就沒有那麼幸運了,層級往往會比較多,這個時候就需要技術上的痛足夠痛,能夠痛到影響業務,能夠痛到影響收入,能夠痛到被競爭對手甩在後面,才能上達天聽。

我們接下來就梳理一下,在這個過程中的那些痛。

二、階段一:單體架構群,多個開發組,統一運維組

致傳統企業朋友:不夠痛就別微服務,有坑      2.1. 階段一的組織狀態

組織狀態相對簡單。

統一的運維組,管理物理機,物理網路,Vmware虛擬化等資源,同時部署上線由運維部負責。

開發組每個業務都是獨立的,負責寫程式碼,不同的業務溝通不多,開發除了做自己的系統外,還需要維護外包公司開發的系統,由於不同的外包公司技術選型差異較大,因而處於煙囪式的架構狀態。

傳統煙囪式架構如下圖所示

致傳統企業朋友:不夠痛就別微服務,有坑      

2.2. 階段一的運維模式

在傳統架構下,基礎設施層往往採取物理機或者虛擬化進行部署,為了不同的應用之間方便相互訪問,多采取橋接扁平二層機房網路,也即所有的機器的IP地址都是可以相互訪問的,不想互相訪問的,多采用防火牆進行隔離。

無論是使用物理機,還是虛擬化,配置是相對複雜的,不是做過多年運維的人員,難以獨立的建立一臺機器,而且網路規劃也需要非常小心,分配給不同業務部門的機器,網段不能衝突。所有這一切,都需要運維部門統一進行管理,一般的IT人員或者開發人員既沒有專業性,也不可能給他們許可權進行操作,要申請機器怎麼辦,走個工單,審批一下,過一段時間,機器就能建立出來。

2.3. 階段一的應用架構

傳統架構資料庫層,由於外包公司獨立開發,或者不同開發部門獨立開發,不同業務使用不同的資料庫,有用Oracle的,有用SQL Server的,有用Mysql的,有用MongoDB的,各不相同。

傳統架構的中介軟體層,每個團隊獨立選型中介軟體:

  • 檔案:NFS,FTP,Ceph,S3

  • 快取:Redis Cluster,主備,Sentinel, Memcached

  • 分散式框架:Spring Cloud,Dubbo,Restful or RPC不同的部門自己選型

  • 分庫分表:Sharding-jdbc,Mycat

  • 訊息佇列:RabbitMQ, Kafka

  • 註冊中心:Zk,Euraka,consul

傳統架構的服務層,系統或者由外包公司開發,或者由獨立團隊開發。

傳統架構前端,各自開發各自的前端。

2.4. 階段一有什麼問題嗎?

其實階段一沒有任何問題,我們甚至能找出一萬個理由說明這種模式的好處。

運維部和開放部是天然分開的,誰也不想管對方,兩邊的老大也是評級的,本相安無事。

機房當然只能運維人員能碰,這裡面有安全的問題,專業性的問題,線上系統嚴肅的問題。如果交給沒有那麼專業的開發去部署環境,一旦系統由漏洞,誰能擔責任,一旦線上系統掛了,又是誰的責任,這個問題問出來,能夠讓任何爭論鴉雀無聲。

資料庫無論使用Oracle, DB2,還是SQL Server都沒有問題,只要公司有足夠的預算,而且效能也的確槓槓的,裡面儲存了大量儲存過程,會使得應用開發簡單很多,而且有專業的乙方幫忙運維,資料庫如此關鍵,如果替換稱為Mysql,一旦抗不出掛了,或者開源的沒人維護,線上出了事情,誰來負責?

中介軟體,服務層,前端,全部由外包商或者乙方搞定,端到端維護,要改什麼招手即來,而且每個系統都是完整的一套,部署方便,運維方便。

其實沒有任何問題,這個時候上容器或者上微服務,的確自找麻煩。

2.5. 什麼情況下才會覺得階段一有問題?

當然最初的痛點應該在業務層面,當使用者的需求開始變的多種多樣,業務方時不時的就要上一個新功能,做一個新系統的時候,你會發現外包公司不是能完全搞定所有的事情,他們是瀑布模型的開發,而且開發出來的系統很難變更,至少很難快速變更。

於是你開始想自己招聘一些開發,開發自己能夠把控的系統,至少能夠將外包公司開發的系統接管過來,這個時候,應對業務部門的需求,就會靈活的多。

但是自己開發和維護就帶來了新的問題,多種多樣的資料庫,根本不可能招聘到如此多樣的DBA,人都非常的貴,而且隨著系統的增多,這些資料庫的lisense也非常的貴。

多種多樣的中介軟體,每個團隊獨立選型中介軟體,沒有統一的維護,沒有統一的知識積累,無法統一保障SLA。一旦使用的訊息佇列,快取,框架出了問題,整個團隊沒有人能夠搞定這個事情,因為大家都忙於業務開發,沒人有時間深入的去研究這些中介軟體的背後原理,常見的問題,如何調優等等。

前端框架也有相同的問題,技術棧不一致,介面風格不一致,根本無法自動做UI測試。

當維護了多套系統之後,你會發現,這些系統各個層次都有很多的共同點,很多能力是可以複用的,很多資料是可以打通的。同樣一套邏輯,這裡也有,那裡也有,同樣型別的資料,這裡一份,那裡一份,但是資訊是隔離的,資料模型不統一,根本無法打通。

當出現這些問題的時候,才是您考慮進入第二個階段。

三、階段二:組織服務化,架構SOA化,基礎設施雲化

       致傳統企業朋友:不夠痛就別微服務,有坑      


3.1. 階段二的組織形態

怎麼解決上面的問題呢?

根據康威定理,組織方面就需要有一定的調整,整個公司還是分運維組和開發組。

由於痛點是從業務層面發生的,開始調整的應該是開發組。

應該建立獨立的前端組,統一前端框架,介面一致,所有人掌握統一的前端開發能力,積累前端程式碼,在有新的需求的時候,能夠快速的進行開發。

建立中介軟體組,或者架構師組,這部分人不用貼近業務開發,每天的任務就是研究如何使用這些中介軟體,如何調優,遇到問題如何Debug,形成知識積累。如果有統一的一幫人專注中介軟體,就可以根據自身的情況,選擇有限幾個中介軟體集中研究,限定業務組只使用這些中介軟體,可保證選型的一致性,如果中介軟體被這個組統一維護,也可以提供可靠的SLA給業務方。

將業務開發組分出一部分來,建立中臺組,將可以複用的能力和程式碼,交由這幾個組開發出服務來,給業務組使用,這樣資料模型會統一,業務開發的時候,首先先看看有哪些現成的服務可以使用,不用全部從零開發,也會提高開發效率。

3.2. 階段二的應用架構

要建立中臺,變成服務為其他業務使用,就需要使用SOA架構,將可以複用的元件服務化,註冊到服務的註冊中心。

對於有錢的企業,可能會採購商用的ESB匯流排,也有使用Dubbo自己封裝稱為服務註冊中心。

接下來就是要考慮,哪些應該拆出來? 最後考慮的是如何拆出來?

這兩個題目的答案,不同的企業不同,其實分為兩個階段,第一個階段是嘗試階段,也即整個公司對於服務化拆分沒有任何經驗,當然不敢拿核心業務上手,往往選取一個邊角的業務,先拆拆看,這個時候拆本身是重要的,其實是為了拆而拆,拆的比較理想化,符合領域驅動設計的最好,如何拆呢?當然是弄一個兩個月,核心員工大家閉門開發,進行拆分和組合,來積累經驗。很多企業目前處於這個階段。

但是其實這個階段的拆法也只能用來積累經驗,因為我們們最初要拆分,是為了快速響應業務請求,而這個邊角的模組,往往不是最痛的核心業務。本來業務就邊角,拆不拆收益不大,而且也沒辦法很好的做能力複用。複用當然都想複用核心能力。

所以其實最重要的是第二個階段,業務真正的服務化的階段。當然要拿業務需求最多的核心業務邏輯下手,才能起到快速響應業務請求,複用能力的作用。

例如考拉最初也是一個使用Oracle,對外只有一個online業務的單體應用,而真正的拆分,就是圍繞核心的下單業務邏輯進行的。    致傳統企業朋友:不夠痛就別微服務,有坑      

那核心業務邏輯中,哪些應該拆出來呢?很多企業會問我們,其實企業自己的開發最清楚。

這個時候經常犯的錯誤是,先將核心業務邏輯從單體應用中拆分出來。例如將下單邏輯形成下單服務,從online服務中拆分出來。

當然不應該這樣,例如兩軍打仗,當炊事班的煙燻著戰士了,是將中軍大營搬出去,還是講炊事班搬出去呢?當然是炊事班了。

另外一點是,能夠形成複用的元件,往往不是核心業務邏輯。這個很好理解,兩個不同的業務,當然是核心業務邏輯不同(要不就成一種業務了),核心業務邏輯往往是組合邏輯,雖然複雜,但是往往不具備複用性,就算是下單,不同的電商也是不一樣的,這家推出了什麼什麼豆,那家推出了什麼什麼券,另一家有個什麼什麼活動,都是核心業務邏輯的不同,會經常變。能夠複用的,往往是使用者中心,支付中心,倉儲中心,庫存中心等等核心業務的周邊邏輯。

所以拆分,應該將這些核心業務的周邊邏輯,從核心業務裡面拆出來,最終Online就剩下下單的核心路徑了,就可以改成下單服務了。當業務方突然有了需求推出一個搶購活動,就可以複用剛才的周邊邏輯了。搶購就成了另一個應用的核心邏輯,其實核心邏輯是傳真引線的,周邊邏輯是儲存資料,提供原子化介面的。

那哪些周邊邏輯應該先拆出來呢?問自己的開發吧,那些戰戰兢兢,自己修改後生怕把核心邏輯搞掛了的組,是自己有動力從核心邏輯中拆分出來的,這個不需要技術總監和架構師去督促,他們有自己的原有動力,是一個很自然的過程。

       致傳統企業朋友:不夠痛就別微服務,有坑      

這裡的原有動力,一個是開發獨立,一個是上線獨立,就像考拉的online系統裡面,倉庫組就想自己獨立出去,因為他們要對接各種各樣的倉儲系統,全球這麼多的倉庫,系統都很傳統,介面不一樣,沒新對接一個,開發的時候,都擔心把下單核心邏輯搞掛了,造成線上事故,其實倉儲系統可以定義自己的重試和容災機制,沒有下單那麼嚴重。物流組也想獨立出去,因為對接的物流公司太多了,也要經常上線,也不想把下單搞掛。

您也可以梳理一下貴公司的業務邏輯,也會有自行願意拆分的業務,形成中臺服務。

當週邊的邏輯拆分之後,一些核心的邏輯,互相怕影響,也可以拆分出去,例如下單和支付,支付對接多個支付方的時候,也不想影響下單,也可以獨立出去。

然後我們再看,如何拆分的問題?

關於拆分的前提,時機,方法,規範等,參考文章微服務化之服務拆分與服務發現

       致傳統企業朋友:不夠痛就別微服務,有坑      

首先要做的,就是原有工程程式碼的標準化,我們常稱為“任何人接手任何一個模組都能看到熟悉的面孔”

例如開啟一個java工程,應該有以下的package:

  • API介面包:所有的介面定義都在這裡,對於內部的呼叫,也要實現介面,這樣一旦要拆分出去,對於本地的介面呼叫,就可以變為遠端的介面呼叫

  • 訪問外部服務包:如果這個程式要訪問其他程式,對於外部訪問的封裝都在這裡,對於單元測試來講,對於這部分的Mock,可以使得不用依賴第三方,就能進行功能測試。對於服務拆分,呼叫其他的服務,也是在這裡。

  • 資料庫DTO:如果要訪問資料庫,在這裡定義原子的資料結構

  • 訪問資料庫包:訪問資料庫的邏輯全部在這個包裡面

  • 服務與商務邏輯:這裡實現主要的商業邏輯,拆分也是從這裡拆分出來。

  • 外部服務:對外提供服務的邏輯在這裡,對於介面的提供方,要實現在這裡。

    另外是測試資料夾,每個類都應該有單元測試,要稽核單元測試覆蓋率,模組內部應該通過Mock的方法實現整合測試。

    接下來是配置資料夾,配置profile,配置分為幾類:

    • 內部配置項(啟動後不變,改變需要重啟)

    • 集中配置項(配置中心,可動態下發)

    • 外部配置項(外部依賴,和環境相關)

      當一個工程的結構非常標準化之後,接下來在原有服務中,先獨立功能模組 ,規範輸入輸出,形成服務內部的分離。在分離出新的程式之前,先分離出新的jar,只要能夠分離出新的jar,基本也就實現了鬆耦合。

      接下來,應該新建工程,新啟動一個程式,儘早的註冊到註冊中心,開始提供服務,這個時候,新的工程中的程式碼邏輯可以先沒有,只是轉呼叫原來的程式介面。

      為什麼要越早獨立越好呢?哪怕還沒實現邏輯先獨立呢?因為服務拆分的過程是漸進的,伴隨著新功能的開發,新需求的引入,這個時候,對於原來的介面,也會有新的需求進行修改,如果你想把業務邏輯獨立出來,獨立了一半,新需求來了,改舊的,改新的都不合適,新的還沒獨立提供服務,舊的如果改了,會造成從舊工程遷移到新工程,邊遷移邊改變,合併更加困難。如果儘早獨立,所有的新需求都進入新的工程,所有呼叫方更新的時候,都改為呼叫新的程式,對於老程式的呼叫會越來越少,最終新程式將老程式全部代理。

      接下來就可以將老工程中的邏輯逐漸遷移到新工程,由於程式碼遷移不能保證邏輯的完全正確,因而需要持續整合,灰度釋出,微服務框架能夠在新老介面之間切換。

      最終當新工程穩定執行,並且在呼叫監控中,已經沒有對於老工程的呼叫的時候,就可以將老工程下線了。

      3.3. 階段二的運維模式

      經過業務層的的服務化,也對運維組造成了壓力。

      應用逐漸拆分,服務數量增多。

      在服務拆分的最佳實踐中,有一條就是,拆分過程需要進行持續整合,保證功能一致。

             致傳統企業朋友:不夠痛就別微服務,有坑      

      而持續整合的流程,往往需要頻繁的部署測試環境。

      隨著服務的拆分,不同的業務開發組會接到不同的需求,並行開發功能增多,釋出頻繁,會造成測試環境,生產環境更加頻繁的部署。

      而頻繁的部署,就需要頻繁建立和刪除虛擬機器。

      如果還是採用上面審批的模式,運維部就會成為瓶頸,要不就是影響開發進度,要不就是被各種部署累死。

      這就需要進行運維模式的改變,也即基礎設施層雲化。

      虛擬化到雲化有什麼不一樣呢?

      首先要有良好的租戶管理,從運維集中管理到租戶自助使用模式的轉換。

      致傳統企業朋友:不夠痛就別微服務,有坑      

      也即人工建立,人工排程,人工配置的集中管理模式已經成為瓶頸,應該變為租戶自助的管理,機器自動的排程,自動的配置。

      其次,要實現基於Quota和QoS的資源控制。

      也即對於租戶建立的資源的控制,不用精細化到運維手動管理一切,只要給這個客戶分配了租戶,分配了Quota,設定了Qos,租戶就可以在運維限定的範圍內,自由隨意的建立,使用,刪除虛擬機器,無需通知運維,這樣迭代速度就會加快。

      再次,要實現基於虛擬網路,VPC,SDN的網路規劃。

             致傳統企業朋友:不夠痛就別微服務,有坑      


             致傳統企業朋友:不夠痛就別微服務,有坑      

      原來的網路使用的都是物理網路,問題在於物理網路是所有部門共享的,沒辦法交給一個業務部門自由的配置和使用。因而要有VPC虛擬網路的概念,每個租戶可以隨意配置自己的子網,路由表,和外網的連線等,不同的租戶的網段可以衝突,互不影響,租戶可以根據自己的需要,隨意的在介面上,用軟體的方式做網路規劃。

      除了基礎設施雲化之外,運維部門還應該將應用的部署自動化。

             致傳統企業朋友:不夠痛就別微服務,有坑因為如果雲端計算不管應用,一旦出現擴容,或者自動部署的需求,雲平臺建立出來的虛擬機器還是空的,需要運維手動上去部署,根本忙不過來。因而云平臺,也一定要管理應用。

      雲端計算如何管理應用呢?我們將應用分成兩種,一種稱為通用的應用,一般指一些複雜性比較高,但大家都在用的,例如資料庫。幾乎所有的應用都會用資料庫,但資料庫軟體是標準的,雖然安裝和維護比較複雜,但無論誰安裝都是一樣。這樣的應用可以變成標準的PaaS層的應用放在雲平臺的介面上。當使用者需要一個資料庫時,一點就出來了,使用者就可以直接用了。    致傳統企業朋友:不夠痛就別微服務,有坑      

      所以對於運維模式的第二個改變是,通用軟體PaaS化。

      前面說過了,在開發部門有中介軟體組負責這些通用的應用,運維也自動部署這些應用,兩個組的界限是什麼樣的呢?

      一般的實踐方式是,雲平臺的PaaS負責建立的中介軟體的穩定,保證SLA,當出現問題的時候,會自動修復。

      而開發部門的中介軟體組,主要研究如何正確的使用這些PaaS,配置什麼樣的引數,使用的正確姿勢等等,這個和業務相關。  致傳統企業朋友:不夠痛就別微服務,有坑      

      除了通用的應用,還有個性化的應用,應該通過指令碼進行部署,例如工具Puppet, Chef, Ansible, SaltStack等。

      這裡有一個實踐是,不建議使用裸機部署,因為這樣部署非常的慢,推薦基於虛擬機器映象的自動部署。在雲平臺上,任何虛擬機器的建立都是基於映象的,我們可以在映象裡面,將要部署的環境大部分部署好,只需要做少量的定製化,這些由部署工具完成。

             致傳統企業朋友:不夠痛就別微服務,有坑      

      下圖是OpenStack基於Heat的虛擬機器編排,除了呼叫OpenStack API基於映象建立虛擬機器之外,還要呼叫SaltStack的master,將定製化的指令下發給虛擬機器裡面的agent。

             致傳統企業朋友:不夠痛就別微服務,有坑      

      基於虛擬機器映象和指令碼下發,可以構建自動化部署平臺NDP

             致傳統企業朋友:不夠痛就別微服務,有坑      

      這樣可以基於虛擬機器映象,做完整的應用的部署和上線,稱為編排。基於編排,就可以進行很好的持續整合,例如每天晚上,自動部署一套環境,進行迴歸測試,從而保證修改的正確性。 致傳統企業朋友:不夠痛就別微服務,有坑      

      進行完第二階段之後,整個狀態如上圖所示。

      這裡運維部門的職能有了一定的改變,除了最基本的資源建立,還要提供自助的操作平臺,PaaS化的中介軟體,基於映象和指令碼的自動部署。

      開發部門的職能也有了一定的改變,拆分稱為前端組,業務開發組,中臺組,中介軟體組,其中中介軟體組合運維部門的聯絡最緊密。

      3.4. 階段二有什麼問題嗎?

      其實大部分的企業,到了這個階段,已經可以解決大部分的問題了。

      能夠做到架構SOA化,基礎設施雲化的公司已經是傳統行業在資訊化領域的佼佼者了。

      中臺開發組基本能夠解決中臺的能力複用問題,持續整合也基本跑起來了,使得業務開發組的迭代速度明顯加快。

      集中的中介軟體組或者架構組,可以集中選型,維護,研究訊息佇列,快取等中介軟體。

      在這個階段,由於業務的穩定性要求,很多公司還是會採用Oracle商用資料庫,也沒有什麼問題。

      實現到了階段二,在同行業內,已經有一定的競爭優勢了。

      3.5. 什麼情況下才會覺得階段二有問題?

      我們發現,當傳統行業不再滿足於在本行業的領先地位,希望能夠對接到網際網路業務的時候,上面的模式才出現新的痛點。

      對接網際網路所面臨的最大的問題,就是巨大的使用者量所帶來的請求量和資料量,會是原來的N倍,能不能撐得住,大家都心裡沒底。

      例如有的客戶推出網際網路理財秒殺搶購,原來的架構無法承載近百倍的瞬間流量。

      有的客戶對接了網際網路支付,甚至對接了國內最大的外賣平臺,而原來的ESB匯流排,就算擴容到最大規模(13個節點),也可能撐不住。

      有的客戶雖然已經用了Dubbo實現了服務化,但是沒有熔斷,限流,降級的服務治理策略,有可能一個請求慢,高峰期波及一大片,或者請求全部接進來,最後都撐不住而掛一片。

      有的客戶希望實現工業互連網平臺,可是接入的資料量動輒PB級別,如果扛的住是一個很大的問題。

      有的客戶起初使用開源的快取和訊息佇列,分散式資料庫,但是讀寫頻率到了一定的程度,就會出現各種奇奇怪怪的問題,不知道應該如何調優。

      有的客戶發現,一旦到了網際網路大促級別,Oracle資料庫是肯定扛不住的,需要從Oracle遷移到DDB分散式資料庫,可是怎麼個遷移法,如何平滑過渡,心裡沒底。

      有的客戶服務拆分之後,原來原子化的操作分成了兩個服務呼叫,如何仍然保持原子化,要不全部成功,要不全部失敗,需要分散式事務,雖然業內有大量的分散式方案,但是能夠承載高併發支付的框架還沒有。

      當出現這些問題的時候,才應該考慮進入第三個階段,微服務化

      四、階段三:組織DevOps化,架構微服務化,基礎設施容器化

             致傳統企業朋友:不夠痛就別微服務,有坑      


      4.1. 階段三的應用架構

      從SOA到微服務化這一步非常關鍵,複雜度也比較高,上手需要謹慎。

      為了能夠承載網際網路高併發,業務往往需要拆分的粒度非常的細,細到什麼程度呢?我們來看下面的圖。

             致傳統企業朋友:不夠痛就別微服務,有坑      

      在這些知名的使用微服務的網際網路公司中,微服務之間的相互呼叫已經密密麻麻相互關聯成為一個網狀,幾乎都看不出條理來。

      為什麼要拆分到這個粒度呢?主要是高併發的需求。

      但是高併發不是沒有成本的,拆分成這個粒度會有什麼問題呢?你會發現等拆完了,下面的這些措施一個都不能少。

      • 拆分如何保證功能不變,不引入Bug——持續整合,參考微服務化的基石——持續整合

      • 靜態資源要拆分出來,快取到接入層或者CDN,將大部分流量攔截在離使用者近的邊緣節點或者接入層快取,參考微服務的接入層設計與動靜資源隔離

      • 應用的狀態要從業務邏輯中拆分出來,使得業務無狀態,可以基於容器進行橫向擴充套件,參考微服務化之無狀態化與容器化

      • 核心業務和非核心業務要拆分,方便核心業務的擴充套件以及非核心業務的降級,參考微服務化之服務拆分與服務發現

      • 資料庫要讀寫分離,要分庫分表,才能在超大資料量的情況下,資料庫具有橫向擴充套件的能力,不成為瓶頸,參考微服務化的資料庫設計與讀寫分離

      • 要層層快取,只有少數的流量到達中軍大營資料庫,參考微服務化之快取的設計

      • 要使用訊息佇列,將原來連續呼叫的多個服務非同步化為監聽訊息佇列,從而縮短核心邏輯

      • 服務之間要設定熔斷,限流,降級策略,一旦呼叫阻塞應該快速失敗,而不應該卡在那裡,處於亞健康狀態的服務要被及時熔斷,不產生連鎖反應。非核心業務要進行降級,不再呼叫,將資源留給核心業務。要在壓測到的容量範圍內對呼叫限流,寧可慢慢處理,也不用一下子都放進來,把整個系統沖垮。

      • 拆分成的服務太多了,沒辦法一個個配置,需要統一的一個配置中心,將配置下發

      • 拆分成的服務太多了,沒辦法一個個看日誌,需要統一的日誌中心,將日誌彙總

      • 拆分成的服務太多了,很難定位效能瓶頸,需要通過APM全鏈路應用監控,發現效能瓶頸,及時修改

      • 拆分成的服務太多了,不壓測一下,誰也不知道到底能夠抗住多大的量,因而需要全鏈路的壓測系統。       致傳統企業朋友:不夠痛就別微服務,有坑

        應用層需要處理這十二個問題,最後一個都不能少,實施微服務,你做好準備了嗎?你真覺得攢一攢springcloud,就能夠做好這些嗎?

        4.2. 階段三的運維模式

        業務的微服務化改造之後,對於運維的模式是有衝擊的。

               致傳統企業朋友:不夠痛就別微服務,有坑      

        如果業務拆成了如此網狀的細粒度,服務的數目就會非常的多,每個服務都會獨立釋出,獨立上線,因而版本也非常多。

        這樣環境就會非常的多,手工部署已經不可能,必須實施自動部署。好在在上一個階段,我們已經實施了自動部署,或者基於指令碼的,或者基於映象的,但是到了微服務階段都有問題。

        如果基於指令碼的部署,指令碼原來多由運維寫,由於服務太多,變化也多,指令碼肯定要不斷的更新,而每家公司的開發人員都遠遠多於運維人員,運維根本來不及維護自動部署的指令碼。那指令碼能不能由開發寫呢?一般是不可行的,開發對於執行環境瞭解有限,而且指令碼沒有一個標準,運維無法把控開發寫的指令碼的質量。

        基於虛擬機器映象的就會好很多,因為需要指令碼做的事情比較少,大部分對於應用的配置都打在映象裡面了。如果基於虛擬機器映象進行交付,也能起到標準交付的效果。而且一旦上線有問題,也可以基於虛擬機器映象的版本進行回滾。

        但是虛擬機器映象實在是太大了,動不動幾百個G,如果一共一百個服務,每個服務每天一個版本,一天就是10000G,這個儲存容量,誰也受不了。

        這個時候,容器就有作用了。映象是容器的根本性發明,是封裝和執行的標準,其他什麼namespace,cgroup,早就有了。

        原來開發交付給運維的,是一個war包,一系列配置檔案,一個部署文件,但是由於部署文件更新不及時,常常出現運維部署出來出錯的情況。有了容器映象,開發交付給運維的,是一個容器映象,容器內部的執行環境,應該體現在Dockerfile檔案中,這個檔案是應該開發寫的。

        這個時候,從流程角度,將環境配置這件事情,往前推了,推到了開發這裡,要求開發完畢之後,就需要考慮環境部署的問題,而不能當甩手掌櫃。由於容器映象是標準的,就不存在指令碼無法標準化的問題,一旦單個容器執行不起來,肯定是Dockerfile的問題。

        而運維組只要維護容器平臺就可以,單個容器內的環境,交給開發來維護。這樣做的好處就是,雖然程式多,配置變化多,更新頻繁,但是對於某個模組的開發團隊來講,這個量是很小的,因為5-10個人專門維護這個模組的配置和更新,不容易出錯。自己改的東西自己知道。

        如果這些工作量全交給少數的運維團隊,不但資訊傳遞會使得環境配置不一致,部署量會大非常多。

        容器作用之一就是環境交付提前,讓每個開發僅僅多做5%的工作,就能夠節約運維200%的工作,並且不容易出錯。

               致傳統企業朋友:不夠痛就別微服務,有坑      

        容器的另外一個作用,就是不可改變基礎設施。

        容器映象有個特點,就是ssh到裡面做的任何修改,重啟都不見了,恢復到映象原來的樣子,也就杜絕了原來我們部署環境,這改改,那修修最後部署成功的壞毛病。

        因為如果機器數目比較少,還可以登入到每臺機器上改改東西,一旦出了錯誤,比較好排查,但是微服務狀態下,環境如此複雜,規模如此大,一旦有個節點,因為人為修改配置導致錯誤,非常難排查,所以應該貫徹不可改變基礎設施,一旦部署了,就不要手動調整了,想調整從頭走釋出流程。

        這裡面還有一個概念叫做一切即程式碼,單個容器的執行環境Dockerfile是程式碼,容器之間的關係編排檔案是程式碼,配置檔案是程式碼,所有的都是程式碼,程式碼的好處就是誰改了什麼,Git裡面一清二楚,都可以track,有的配置錯了,可以統一發現誰改的。

        4.3. 階段三的組織形態

        到了微服務階段,實施容器化之後,你會發現,然而本來原來運維該做的事情開發做了,開發的老大願意麼?開發的老大會投訴運維的老大麼?

        這就不是技術問題了,其實這就是DevOps,DevOps不是不區分開發和運維,而是公司從組織到流程,能夠打通,看如何合作,邊界如何劃分,對系統的穩定性更有好處。

               致傳統企業朋友:不夠痛就別微服務,有坑      

        其實開發和運維變成了一個融合的過程,開發會幫運維做一些事情,例如環境交付的提前,Dockerfile的書寫。

        運維也可以幫助研發做一些事情,例如微服務之間的註冊發現,治理,配置等,不可能公司的每一個業務都單獨的一套框架,可以下沉到運維組來變成統一的基礎設施,提供統一的管理。

        實施容器,微服務,DevOps後,整個分工介面就變成了下面的樣子。

               致傳統企業朋友:不夠痛就別微服務,有坑      

        在網易就是這個模式,杭州研究院作為公共技術服務部門,有運維部門管理機房,上面是雲平臺組,基於OpenStack開發了租戶可自助操作的雲平臺。PaaS元件也是雲平臺的一部分,點選可得,提供SLA保障。容器平臺也是雲平臺的一部分,並且基於容器提供持續整合,持續部署的工具鏈。

        微服務的管理和治理也是雲平臺的一部分,業務部門可以使用這個平臺進行微服務的開發。

        業務部門的中介軟體組或者架構組合雲平臺組溝通密切,主要是如何以正確的姿勢使用雲平臺元件。

        業務部門分前端組,業務開發組,中臺開發組。

        五、如何實施微服務,容器化,DevOps

        實施微服務,容器化,DevOps有很多的技術選型。

        其中容器化的部分,Kubernetes當之無愧的選擇。但是Kubernetes可不僅僅志在容器,他是為微服務而設計的。對於實施微服務各方面都有涉及。

        詳細分析參加為什麼 kubernetes 天然適合微服務  致傳統企業朋友:不夠痛就別微服務,有坑但是Kubernetes對於容器的執行時生命週期管理比較完善,但是對於服務治理方面還不夠強大。

        因而對於微服務的治理方面,多選擇使用Dubbo或者SpringCloud。使用Dubbo的存量應用比較多,相對於Dubbo來講,SpringCloud比較新,元件也比較豐富。但是SpringCloud的元件都不到開箱即用的程度,需要比較高的學習曲線。

               致傳統企業朋友:不夠痛就別微服務,有坑      

        因而基於Kubernetes和SpringCloud,就有了下面這個微服務,容器,DevOps的綜合管理平臺。包含基於Kubernetes的容器平臺,持續整合平臺,測試平臺,API閘道器,微服務框架,APM應用效能管理。

               致傳統企業朋友:不夠痛就別微服務,有坑主要為了解決從階段一到階段二,或者階段二到階段三的改進中的痛點。

        下面我們列舉幾個場景。

        場景一:架構SOA拆分時,如何保證迴歸測試功能集不變

        前面說過,服務拆分後,最怕的是拆完了引入一大堆的bug,通過理智肯定不能保證拆分後功能集是不變的,因而需要有迴歸測試集合保證,只要測試集合通過了,功能就沒有太大的問題。

        迴歸測試最好是基於介面的,因為基於UI的很危險,有的介面是有的,但是UI上不能點,這個介面如果有Bug,就被暫時隱藏掉了,當後面有了新的需求,當開發發現有個介面能夠呼叫的時候,一呼叫就掛了。

               致傳統企業朋友:不夠痛就別微服務,有坑有了基於Restful API的介面測試之後,可以組成場景測試,將多個API呼叫組合成為一個場景,例如下單,扣優惠券,減庫存,就是一個組合場景。

        另外可以形成測試集合,例如冒煙測試集合,當開發將功能交付給測試的時候,執行一下。再如日常測試集合,每天晚上跑一遍,看看當天提交的程式碼有沒有引入新的bug。再如迴歸測試集合,上線之前跑一遍,保證大部分的功能是正確的。

        場景二:架構SOA化的時候,如何統一管理並提供中臺服務

        當業務要提供中臺服務的時候,中臺服務首先希望能夠註冊到一個地方,當業務組開發業務邏輯的時候,能夠在這個地方找到中臺的介面如何呼叫的文件,當業務組的業務註冊上來的時候,可以進行呼叫。

               致傳統企業朋友:不夠痛就別微服務,有坑      

        在微服務框架普通的註冊發現功能之外,還提供知識庫的功能,使得介面和文件統一維護,文件和執行時一致,從而呼叫方看著文件就可以進行呼叫。

        另外提供註冊,發現,呼叫期間的鑑權功能,不是誰看到中臺服務都能呼叫,需要中臺管理員授權才可以。

        為了防止中臺服務被惡意呼叫,提供賬戶審計功能,記錄操作。

        場景三:服務SOA化的時候,如何保證關鍵服務的呼叫安全   致傳統企業朋友:不夠痛就別微服務,有坑      

        有的服務非常關鍵,例如支付服務,和資金相關,不是誰想呼叫就能呼叫的,一旦被非法呼叫了,後果嚴重。

        在服務治理裡面有路由功能,除了能夠配置靈活的路由功能之外,還可以配置黑白名單,可以基於IP地址,也可以基於服務名稱,配置只有哪些應用可以呼叫,可以配合雲平臺的VPC功能,限制呼叫方。

        場景四:架構SOA化後,對外提供API服務,構建開放平臺

               致傳統企業朋友:不夠痛就別微服務,有坑      

        架構SOA化之後,除了對內提供中臺服務,很多能力也可以開放給外部的合作伙伴,形成開放平臺。例如你是一家物流企業,除了在你的頁面上下單寄快遞之外,其他的電商也可以呼叫你的API來寄快遞,這就需要有一個API閘道器來管理API,對接你的電商只要登入到這個API閘道器,就能看到API以及如何呼叫,API閘道器上面的文件管理就是這個作用。

        另外API閘道器提供介面的統一認證鑑權,也提供API介面的定時開關功能,靈活控制API的生命週期。

        場景五:網際網路場景下的灰度釋出和A/B測試

        接下來我們切換到網際網路業務場景,經常會做A/B測試,這就需要API閘道器的流量分發功能。

        例如我們做網際網路業務,當上一個新功能的 時候,不清楚客戶是否喜歡,於是可以先開放給山東的客戶,當HTTP頭裡面有來自山東的欄位,則訪問B系統,其他客戶還是訪問A系統,這個時候可以看山東的客戶是否都喜歡,如果都喜歡,就推向全國,如果不喜歡,就撤下來。

        場景六:網際網路場景下的預發測試

        這個也是網際網路場景下經常遇到的預發測試,雖然我們在測試環境裡面測試了很多輪,但是由於線上場景更加複雜,有時候需要使用線上真實資料進行測試,這個時候可以線上上的正式環境旁邊部署一套預發環境,使用API閘道器將真實的請求流量,映象一部分到預發環境,如果預發環境能夠正確處理真實流量,再上線就放心多了。

        場景七:網際網路場景下的效能壓測

        網際網路場景下要做線上真實的效能壓測,才能知道整個系統真正的瓶頸點。但是效能壓測的資料不能進真實的資料庫,因而需要進入影子庫,效能壓測的流量,也需要有特殊的標記放在HTTP頭裡面,讓經過的業務系統知道這是壓測資料,不進入真實的資料庫。

        這個特殊的標記要在API閘道器上新增,但是由於不同的壓測系統要求不一樣,因而需要API閘道器有定製路由外掛功能,可以隨意新增自己的欄位到HTTP頭裡面,和壓測系統配合。

        場景八:微服務場景下的熔斷,限流,降級

        微服務場景下,大促的時候,需要進行熔斷,限流,降級。這個在API閘道器上可以做,將超過壓測值的流量,通過限流,攔在系統外面,從而保證儘量的流量,能夠下單成功。

        在服務之間,也可以通過微服務框架,進行熔斷,限流,降級。Dubbo對於服務的控制在介面層面,SpringCloud對於服務的管理在例項層面,這兩個粒度不同的客戶選擇不一樣,都用Dubbo粒度太細,都用SpringCloud粒度太粗,所以需要可以靈活配置。

        致傳統企業朋友:不夠痛就別微服務,有坑      場景九:微服務場景下的精細化流量管理。

             致傳統企業朋友:不夠痛就別微服務,有坑      

        在網際網路場景下,經常需要對於流量進行精細化的管理,可以根據HTTP Header裡面的引數進行分流,例如VIP使用者訪問一個服務,非VIP使用者訪問另一個服務,這樣可以對高收入的使用者推薦更加精品的產品,增加連帶率。

        本文轉自 :劉超的通俗雲端計算。

        致傳統企業朋友:不夠痛就別微服務,有坑


        來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31562044/viewspace-2285779/,如需轉載,請註明出處,否則將追究法律責任。

        相關文章