HRMM 想了解 Microservice,于是我講了三個故事
一天我司招才貓姐(HR 大人)問我,你給我解釋一下 Microservice 是什么吧。故成此文。一切都是從一個創(chuàng)業(yè)公司開始的。
***章:從集中到分權(quán)
最近的創(chuàng)業(yè)潮非?;鸨?,我禁不住誘惑也摻和了進去,創(chuàng)建了一家公司。為了表達我的抱負,取千秋萬代,一統(tǒng)江湖之意。我給公司定下了一個非常響亮的名字叫做——一統(tǒng)。
故事
雖說叫做一統(tǒng)但是凡是都要從頭開始,公司成立之初有五個成員:羅密歐,朱麗葉,維克多,布拉伯還有老大——我。我們五個人都是工程師出身,自身具備了非常優(yōu)秀的學(xué)習(xí)能力,各個都是從業(yè)務(wù)到代碼的好手,五個人一起做策劃,搞市場,寫程序,做運維,面對客戶;可謂你中有我,我中有你,努力拼搏,好不熱鬧。為了吉利,我們找了一個車庫作為機房和資料室,上至合同,下至代碼,全都放在里面。這就是一統(tǒng)最初的樣子。

雖然創(chuàng)業(yè)艱難,大部分公司都在前兩年倒下了,但是我大一統(tǒng)不但沒有倒掉,還意外的得到了增長??蛻魪漠敵醯囊患颐驮龅揭话偌?。這樣即使我們的團隊再出色也應(yīng)付不了這么多的客戶了。掙錢還是要命呢?

命得要,錢也得掙!怎么辦呢?招人吧!我們絞盡腦汁搜羅(挖角)市場上的人才,組成了巨型一統(tǒng)團隊。我們認為我們團隊中的任何成員都應(yīng)該跟初創(chuàng)時期的五個人一樣,能攻能守,內(nèi)外兼修,但是……我們發(fā)現(xiàn)這是不可能的,有些人擅長寫代碼而非面對客戶,有些人善于做市場但是不喜歡算財務(wù)。后來出現(xiàn)了更加讓人撓頭的事情,有一個財務(wù)流程,問了5-6個人竟然沒有一個人能夠完整的串起來。于是,我一個一個的問,***才把整個流程從這些碎片知識里面串聯(lián)起來。
這樣的團隊的服務(wù)質(zhì)量可想而知,不久就接到了數(shù)十件客戶投訴。競爭對手趁機搶占市場,一個欣欣向榮的公司瞬間就搖搖欲墜了。

為了留住客戶,我們必須在擴張的同時能夠保證服務(wù)質(zhì)量。我發(fā)現(xiàn)目前最重要的問題就是職責(zé)不清晰,大家不知道自己應(yīng)該干什么也不清楚怎么干,于是我抽調(diào)了各個業(yè)務(wù)部分的精干力量,總結(jié)流程,形成了客戶及市場、財務(wù)/合同、技術(shù)運維、管理團隊四個獨立的業(yè)務(wù)部分。采取內(nèi)部招聘的方式將人力分配到了這四個部門中。我期望將大家從紛繁的知識體系中解脫出來,每一個不需要了解那么多的知識,集中力量關(guān)注自己的問題以提升效率和服務(wù)質(zhì)量。

在此次結(jié)構(gòu)調(diào)整之后,大家的工作效率明顯提升了。抱怨知識結(jié)構(gòu)太復(fù)雜,無法短期適應(yīng)工作的聲音消失了。一個月之后,我們做了一個抽樣調(diào)查,發(fā)現(xiàn)大家對自己的工作范圍和內(nèi)容都了如指掌。一些客戶又重新和我們簽訂了合同。
正當我沾沾自喜的時候,發(fā)生了一個重大事件。由于我們的資料室是對全公司開放的,任何成員都可以查看或修訂其中的信息。客戶及市場部的一個員工平時非常好學(xué),對財務(wù)方面的知識掌握的非常系統(tǒng)。有一天,公司急需草擬一份財務(wù)清單,但是這個任務(wù)非常耗時,財務(wù)部門的同時當時正在月末審核,無暇抽身。這位熱心的同學(xué)就憑借自己出色的能力從資料室取來相應(yīng)的材料完成了清單。三天后,財務(wù)部的羅密歐準備細化這個清單。但是清單的內(nèi)容讓他著實吃了一驚——清單上的填寫內(nèi)容和他們部門內(nèi)約定格格不入。羅密歐只得自己重新完成了清單。一來一去讓他的工作耽擱了一天,羅密歐向我抱怨道。無獨有偶,其他部門也發(fā)生了同樣的事情。這讓我意識到只是把人員的職責(zé)進行劃分并不能徹底解決問題。我們不能再繼續(xù)混用一個資料室了,因為這樣人人都可以任意修改各種資料,安全性不好不說還會造成填寫格式混亂。于是我把財務(wù)部的資料放在了另一個獨立的屋子里,并給羅密歐單獨配了鑰匙。這樣,任何想填寫財務(wù)清單的人只能找財務(wù)部的人所要單據(jù),而當單據(jù)繳回的時候也必須經(jīng)過財務(wù)部的審核。鑒于財務(wù)部每個月底都會很忙,在那時我會臨時抽調(diào)人手去幫忙。
我希望對其他部門做相應(yīng)的整改,但這種動作幅度畢竟很大,因此,一段時間內(nèi)還會有多個部門共用資料室。經(jīng)過一個月的努力,我們最終還是淘汰了公用資料室。為每一個部門都配備了獨立資料室。雖然需要繳納更多的房租,但是各部門再也沒有犯之前的錯誤。

從故事到項目
大多數(shù)項目也會像我們的創(chuàng)業(yè)公司一樣,一開始大家一起干活,每一個人都是沖鋒陷陣多面手。大家一起組成了應(yīng)用程序的全部,而我們的車庫就是數(shù)據(jù)庫。這種組織結(jié)構(gòu)代表了典型的 monolithic application。這種系統(tǒng)的邏輯架構(gòu)是類似這樣的。

在項目的早起,業(yè)務(wù)簡單,吞吐不大,這種結(jié)構(gòu)清晰,易于理解的架構(gòu)非常實用。但是隨著業(yè)務(wù)的增大,混在一起的代碼不易理解。而最容易想到的解決辦法就進行職責(zé)的劃分。一統(tǒng)公司一開始在維持車庫結(jié)構(gòu)的情況下僅僅把人員上做了拆分。這種情形在實際項目中也存在。系統(tǒng)進入了多個服務(wù)共享一個數(shù)據(jù)庫的階段,而集成點在數(shù)據(jù)庫上。

這種職責(zé)劃分但又維持數(shù)據(jù)庫集成的方式只應(yīng)當作為過度階段存在。程序永遠都是邏輯+數(shù)據(jù),而數(shù)據(jù)的混雜談不上職責(zé)的獨立。長期維持這種數(shù)據(jù)集成的狀態(tài)容易出現(xiàn)業(yè)務(wù)下行,數(shù)據(jù)表達不一致等問題。從邏輯+數(shù)據(jù)的整體劃分邊界(稱為模塊,或者服務(wù))勢在必行。而在邊界劃定之后,就需要考慮獨立的服務(wù)之間如何進行協(xié)作了。
#p#
第二章:協(xié)作
現(xiàn)在我們的資料室都獨立了,再也沒有辦法像以前一樣有需要就去公共資料室里取資料了。那么我們應(yīng)該如何進行協(xié)作呢?
故事
一個非常自然的想法是把各部門用業(yè)務(wù)流程穿起來。例如,如果洽談一個訂單,先由客戶及市場部進行調(diào)查和談判,然后由技術(shù)部制定解決方案,管理部審批之后由財務(wù)合同部擬定合同,最終遞交管理部簽署。這種協(xié)作方式我們不妨叫他 串聯(lián)協(xié)作。

為了將這一方案執(zhí)行下去,我們對各個部門的人員進行了培訓(xùn)。例如,對于對于技術(shù)部,如果是洽談一個訂單,那么技術(shù)部需要給出解決方案,完成之后需要將方案遞交管理部審批。類似的業(yè)務(wù)有很多,每一個業(yè)務(wù)各個部門任務(wù)都不同,而下游接收的部門也不一樣。但是我的同事們還是克服了困難,將它們爛熟于胸。
業(yè)務(wù)變化是最平常的,一變就是一大把?,F(xiàn)在對于洽談訂單的業(yè)務(wù),我們需要在技術(shù)方案給出之后先給財務(wù)部進行預(yù)算審核再遞交管理部。這需要重新培訓(xùn)三個部門的人,洗腦一樣的把他們之前的流程抹掉。一個業(yè)務(wù)變化還好,但是一下二三十個業(yè)務(wù)發(fā)生變化讓大家抓狂。甚至有人說這和之前一大坨人一起做所有事情的時候沒有什么差別??磥磉@種業(yè)務(wù)串聯(lián)的方式是行不通了。
所謂我不入地獄誰入地獄,這種情況下我挺身而出,入住市場部——因為這個部門是直接為客戶服務(wù)的。我對所有的流程了如指掌,當業(yè)務(wù)來了的時候,有我去對業(yè)務(wù)進行協(xié)調(diào)。例如,當一個洽談訂單的業(yè)務(wù)到來的時候,我會先將他交給客戶市場部進行談判;結(jié)束后市場部將需求和意向書交給我,我再把需求交給技術(shù)部去制定解決方案;方案制定完畢之后技術(shù)部會把方案返回給我,我再把結(jié)果交給財務(wù)部審核…如此進行。這樣,每一個部門就不會由于業(yè)務(wù)變化重新接受培訓(xùn)了,也不用記住他們的下游應(yīng)該是誰。大家覺得,職責(zé)明確多了,工作輕松多了。

這種協(xié)作方式我們不妨稱之為 業(yè)務(wù)調(diào)度員式的協(xié)作。
現(xiàn)在我儼然成為了流程的中心,其他業(yè)務(wù)部門不需要關(guān)注業(yè)務(wù)流程的變化。這給我們增加了很多靈活性,因為我一個人的變化速度要比一群人的變化速度快得多(你是獨裁者嗎喂)。但是我的大腦總是有限的,一年之后,經(jīng)歷了三四輪的業(yè)務(wù)變化,我已經(jīng)開始不能準確的回憶某些業(yè)務(wù)細節(jié)。我不得不開始頻繁的查詢我的業(yè)務(wù)筆記來確定我的下一步操作;此外,不停的往各部門送信也令我不堪重負。這時候,我希望其他人能夠為我分擔。我決定化被動為主動,不由我主動聯(lián)絡(luò)各個部門,而由各個部門主動接受任務(wù)。我在公司安裝了一個 大喇叭,話筒就在我的辦公室里。當一個訂單洽談業(yè)務(wù)到來的時候我就朝著喇叭嚎:新訂單來啦??蛻艉褪袌霾繉iT關(guān)注新訂單,因為按照流程,訂單到來之后市場部要盡快投入談判。于是他們會主動開始行動。當市場部工作完畢之后,他們會將談判的結(jié)果、需求以及意向書拿到我的辦公室里。我會再嚎:需求來啦。此時,技術(shù)部會從我這里拿走這些資料資料并開始工作。如此往復(fù),直到項目完成。

這種協(xié)作方式令我不必再操心信息在各部門之間的流轉(zhuǎn)。各部門知道他們應(yīng)該何時介入,我只需要對著大喇叭喊自然會有相關(guān)的部門將活干完。這樣,我作為業(yè)務(wù)的中轉(zhuǎn)中心,工作量不會隨著業(yè)務(wù)的增長顯著的增大(只要喊話就行了,至多就是增加喊話種類),而各部門也不用關(guān)心自己的下游到底是誰,只需要關(guān)心我喊的話就行了。這種協(xié)作方式不妨稱之為 公司廣播??雌饋磉@是一種非常方便的形式。但是這真的就又快又省嗎?
有一天,來了一個新的訂單。在我接到意向書和需求之后,我照例喊話:需求來啦!接著,我就出去吃飯了(真是資本家啊你)。等我回到了辦公室,發(fā)現(xiàn)文檔已經(jīng)被拿走了,而結(jié)果還沒有送過來。時間一天一天過去了,我手頭的新訂單越積越多,需求文檔和意向書源源不斷的送過來。到了第三天我實在是受不了了,想去查找文檔的去向和任務(wù)的完成狀況。這時候我才發(fā)現(xiàn)我根本無從下手,因為我不知道文檔是誰拿走的,于是我便一個部門一個部門的去詢問??墒怯捎跇I(yè)務(wù)的發(fā)展,現(xiàn)在我們已經(jīng)有20多個部門了,這種非常規(guī)的詢問不僅讓我跑斷了腿,而且為了查證,需要翻閱各部門成噸的業(yè)務(wù)日志,各部門的部長對此也頗有微辭。我終于意識到——這種協(xié)作方式在令結(jié)構(gòu)松散靈活的同時也極大的增加了監(jiān)管的難度。必須采取額外的投入來彌補這一短板。
于是,專門監(jiān)視各部門動向的“紀檢委”:監(jiān)管部出現(xiàn)了。一開始,我只是想確認一下各部門運作是否正常,有沒有由于天災(zāi)人禍而出現(xiàn)團滅的現(xiàn)象。出于不對各部門添加新的壓力的愿望,監(jiān)管部會定期去確定各部門走一圈看看是否都在好好干活(真是討人嫌的部門啊),就像這樣。

但是隨著業(yè)務(wù)的發(fā)展,我希望得到各個部門更加詳盡的信息,例如,各部門是否積壓了大量任務(wù)而需要幫助,在處理過程中是否由于流程不合理而無法繼續(xù)下去等等。需要收集的數(shù)據(jù)已經(jīng)遠遠超過了監(jiān)管部跑腿的速度。怎么辦呢?如果我手頭沒有什么錢,我可能會降低監(jiān)管部工作的周期,例如之前是半天一次,現(xiàn)在改成兩天一次。但是我是土豪,于是我制定了監(jiān)管匯報單,強制各部門在狀況出現(xiàn)問題的時候主動向監(jiān)管部匯報,就像這樣。

從故事到項目
我們真正的開始考慮服務(wù)之間如何進行協(xié)作了。和一統(tǒng)公司的做法一樣,最容易想到的就是業(yè)務(wù)串聯(lián)。業(yè)務(wù)首先由***個服務(wù)處理,處理之后***個服務(wù)調(diào)用第二個服務(wù)繼續(xù)處理,直至業(yè)務(wù)全部處理完畢。這樣,我們就得到了這樣的系統(tǒng)架構(gòu):

正如故事中說的一樣,這種業(yè)務(wù)的串聯(lián)難以應(yīng)對業(yè)務(wù)流發(fā)生的變化。同時,由于服務(wù)之間互相直接耦合,集成點多,難以做到獨立進行部署。業(yè)務(wù)調(diào)度員 的方式是一種很好的改進。如果你還記得那位勤勞的調(diào)度員(我),那么你就一定認識 Composer 這個特殊的服務(wù):我們使用 它進行業(yè)務(wù)流的分發(fā)與控制。這樣,服務(wù)僅僅和 composer 進行對接,不需要考慮業(yè)務(wù)流的問題。既明確了職責(zé)又可以進行獨立部署。以下就是這種協(xié)作方式的架構(gòu):

而最復(fù)雜的公司廣播 則是變直接調(diào)用為事件觸發(fā)。使用 事件 隔離了各自的模型。系統(tǒng)結(jié)構(gòu)更加松散靈活。

隔離和協(xié)作的矛盾
從躊躇滿志的創(chuàng)業(yè)開始到現(xiàn)在,我感慨于業(yè)務(wù)的擴大和公司規(guī)模的發(fā)展。也有一些會議例如 PCon 希望我們能夠去介紹的結(jié)構(gòu)劃分和協(xié)作模式。但是每當我在工作之余靜靜思考的,卻感到一些厭倦。我們的協(xié)作真的好嗎?隨著職責(zé)的劃分,我們越來越專業(yè)化,互不影響的工作方式極大的增加了我們的效率,良好的隔離讓我們的失誤不至于擴散并能夠橫向擴展;而監(jiān)控系統(tǒng)也告訴我們一切盡在掌握。但是隔離同時也是壁壘。為了協(xié)作,我們在這些壁壘上開了些小孔,為了嚴格控制進出,我們制定了越來越多的規(guī)條,例如,信件應(yīng)該怎么寫,單據(jù)應(yīng)該怎么填?;仡^看去,成百上千的規(guī)約連我也不能盡數(shù),當我需要對我的公司做出變化的時候,如果變化僅僅發(fā)生在各個部門內(nèi)部,這種結(jié)構(gòu)的優(yōu)勢就顯露無遺。但是如果設(shè)計到部門之間的協(xié)作,甚至部門的拆分合并,就會變得異常艱難。由于部門和規(guī)約的耦合是存在于腦內(nèi)的,并不顯露在外,修改已經(jīng)存在的規(guī)約和部門結(jié)構(gòu)往往不現(xiàn)實,只能花更多的錢去組建新的部門,逐步介入公司業(yè)務(wù)后淘汰舊有的部門。而這種周期動輒是以月計算的。有的時候,可能寧可去接受新的方式從頭開始,賣掉舊的公司,創(chuàng)建新的公司,然后繼續(xù)輪回。
隔離既創(chuàng)造了靈活的單點變化也擴展造就了整體的僵化。細小的部門劃分不能解決這個問題,因為部門越多,規(guī)約越多,實施成本越高(在例子中我們并沒有考慮資料室的房租,監(jiān)控的支出,但是現(xiàn)實中這往往是一個決定性因素)。單個部門結(jié)構(gòu)的簡化造就了整體的復(fù)雜。
因此,分部門就一定好嗎?業(yè)務(wù)調(diào)度員就沒有公司廣播好嗎?答案應(yīng)該來源于你的現(xiàn)實,而不是理論。如果讓我重來一次,我可能會慢一點,再慢一點。未來無法預(yù)計,針對當下的痛點做出反應(yīng)可能不是***的,但是卻是一個容易理解的思路。
實際項目中也是一樣。就像武俠小說中的一樣,威力越大的招數(shù)其使用限制也就越多。一方面,系統(tǒng)結(jié)構(gòu)越來松散越靈活,變化變得容易;另一方面,系統(tǒng)越來越復(fù)雜,維護越來越困難。當維護困難到一定程度不得不將其提上議事日程的時候?qū)J卤O(jiān)督與維護的工作就出現(xiàn)了,這種維護不同以往。維護者既要有維護知識又必須了解這個復(fù)雜系統(tǒng)的運作方式。別忘了,虛擬化、云、Devops 除了概念上的光鮮又復(fù)雜又花錢啊!
慢慢進化,慎重的考慮并決定是否選用 Microservice,然后做好維護吧。
#p#
第三章:Microservice
在前面的內(nèi)容中,哪種方式可以稱為 microservice 架構(gòu)呢?故事里面公司組織結(jié)構(gòu)演化分成了幾個部分,并不是每一個階段代表的結(jié)構(gòu)都可以稱之為 microservice:
***個階段是多個部門共用一個資料室,這種情況往往并沒有擺脫數(shù)據(jù)庫集成的事實(有些項目使用 Schema 對訪問進行隔離,不在此列),不能稱為 microservice;
第二個階段是各個部門有自己的資料室,這是一個非常重要的改變,直到此時,各個部門才實現(xiàn)了完全的隔離,但是還足以稱為 microservice;
第三個階段分三類:
首先是串聯(lián)協(xié)作。在這種方式下,一個部門的變化往往影響了其他部門,因為每一個部門都需要知道業(yè)務(wù)的上游部門和下游部門,因此有比較緊密的耦合關(guān)系,無法獨立變化。因此不足以稱為 microservice;
其次是業(yè)務(wù)調(diào)度員。這種方式下部門自身的變化不會擴散到其他部門,因此是可以獨立決定和操作,只要部門足夠小,這種結(jié)構(gòu)可以稱之為 microservice了;
第三是公司廣播。這種方式下的部門耦合更加松散,可以獨立進行變化,在部門足夠小的前提下可以稱之為 microservice。
我們的初衷是什么呢?構(gòu)造一個系統(tǒng)能橫向擴展以滿足業(yè)務(wù)伸縮性,提供靈活變化的能力,又希望變化的影響不要擴散。因此,如果一個架構(gòu)可以稱之為 microservice 架構(gòu),那么意味著:
每一個 Service 可以進行獨立部署;
每一個 Service 都足夠小,完成完整的定義清晰的職責(zé);
業(yè)務(wù)調(diào)度員和公司廣播兩個例子的組織結(jié)構(gòu)都可以成為 microservice 架構(gòu)。但是他們之間并沒有絕對的優(yōu)劣之分。選用哪一種應(yīng)當取決于實際要求。
寫在***
Microservice 不是一種科學(xué),而僅僅是實踐。就像是 OO 一樣。最終應(yīng)當是需求,是人,決定架構(gòu)而非架構(gòu)決定需求。Microservice 是為 Business Capability 而建,是根據(jù)實際(或者痛點)做出的抉擇。他解決了一些問題,但是并不能肯定就是今后軟件的發(fā)展方向。硬件的革新——不論是近期的電池技術(shù)的發(fā)展,還是近乎黑科技的量子態(tài)傳輸,量子計算都有可能影響甚至顛覆今天形成的軟件開發(fā)手段。就像是當年大家為了追求***的執(zhí)行效率試圖將代碼塞進 64K 的代碼段一樣,我們今天奉為經(jīng)典的東西未來可能只是茶余飯后的談資。我們能做的只有保持開放的心態(tài),堅持辯證的觀點,堅持從實際出發(fā)(我當年政治一定得高分了),尋找出最合適的解決方案。這也就是我們不稱自己為碼農(nóng)的理由之一吧。
原文鏈接:http://insights.thoughtworkers.org/how-to-introduce-microservices