GitChat · 架構 | 爲何微服務實施那麼難?如何高效推動微服務架構演進

GitChat 做者:顧宇
原文:爲何微服務實施那麼難?如何高效推動微服務架構演進
關注公衆號:GitChat 技術雜談,一本正經的講技術html

前言

筆者從 2013 年加入 ThoughtWorks 至今共 4年時間。在這 4 年的時間裏,我分別以 開發人員, DevOps 工程師、DevOps 諮詢師、微服務架構師以及微服務諮詢師的角色參與了共計 7 個產品和項目的微服務諮詢和實施。其中有有成功,有失敗,有反思,更多的是學習和總結。如下是我這些年來在微服務諮詢上的經驗總結,但願能給陷入微服務實施困境的人帶來一些幫助。git

難點1:「一步到位」的認知錯覺

這些年微服務大紅大紫,可是真正可以拿出來作爲可實踐的案例少之又少。大部分的微服務案例只能看到微服務架構的「演進結果」,可是看不到微服務架構的「演進過程」。這就像每一個人看到一個架構的高峯,卻沒有看到攀登高峯的路徑。數據庫

這就給不少架構師一個假象:微服務的架構是經過能力極高的架構師一步到位設計出來的。編程

這和不少團隊自上而下的架構設計感覺和類似。因而架構師們蜂擁而至,各類分析方法論層出不窮,討論和分享絡繹不絕。然而真正落地實施的卻不多,使得微服務在網絡上慢慢變成了一種「玄學」:微服務的實施在「理論研究」的階段。安全

這違反了軟件架構的最基本規律:架構是解決當前的需求和痛點演進的,而沒法對沒有出現的問題和痛點進行設計。所以,一步到位的總體的微服務架構設計徹底沒有必要。何況一個集中化的設計,很難體現微服務的輕量級優點。網絡

我相信技術的發展必定是向不斷下降成本的方向上發展的。若是新技術沒有下降成本反而提高了成本,要麼這個新技術有問題,要麼必定是姿式不對,走錯了路。架構

所以,準備實施微服務必定要有一個長期的思想準備。不過跨過了最初的門檻以後,剩下的工做能夠被複制並且速度會愈來愈快。框架

難點2:「架構師精英主義」

不少產品對架構師的依賴很大,即「架構師精英主義」:認爲產品架構只有這個組織的「技術精英」——架構師才能夠完成,而團隊其它成員只須要實現架構師的設計就能夠。這是大型企業和大型系統的常見問題,這來源於長期的重量級企業級架構習慣。運維

而微服務則相似於一種「敏捷邊際革命」:即由一個不超過2~8我的的小團隊就能夠完成的功能。並且這種規模的團隊即便從整個產品團隊移除也對總體產品的研發進度沒有影響。所以,即便失敗了不會帶來太多的損失。不過,當第一個微服務改形成功,那麼成功經驗的複製帶來的乘數效應卻能帶來很大的收益。微服務

從架構改造投資的風險收益比來看,這是很是划算的。

所以,微服務團隊徹底不必大張旗鼓,只須要兩三我的就能夠動工。可是,誰也沒有微服務的實踐經驗啊,萬一失敗了怎麼辦?

這就帶來了下一個難點。

難點3:缺少一個信任並鼓勵創新的環境

面對未知的領域,失敗再所不免。而面對這個不肯定性頻發的世界,成功和失敗每每再也不重要:也許今天的失敗,明天再看就是成功,反之亦然。

成功意味只是代表結果符合本身的假設預期,而失敗僅僅意味着結果不符合本身的假設預期。可是不管成敗,咱們都能從行動的過程當中有所學習和反思,而這樣的經驗纔是研發活動中最有價值的。

然而,不少組織,尤爲「精英主義」的產品團隊,責任和壓力每每從上至下分解。因爲組織龐大,金字塔的結構每每會構建一種以「不信任」爲基礎的制度。這種制度每每營造了一種「寧肯不做爲,也不能犯錯」的文化。因爲上層則須要對失敗負責,使得任何創新只是一個停留在組織上層的想法,難以落實推動。在這種狀況下,組織的長期合做造成了穩定的工做習慣和思惟定勢,並造成了利益平衡,這會使得整個組織在面對創新的時候「卡殼」。

當微服務以一種政治任務從上而下派發的時候,爲了不失敗,團隊內部會相互推諉。經過不斷的分析討論和設計來論證這個事情的難度。在我看來,只要想搞,就必定能找到辦法,而不是先設想出一堆尚未遇到的問題和責任。在行進中解決問題是比設計和討論更加有效率的方法。

而組織解決「卡殼」的辦法就是引入「背鍋俠」:例如新聘請的架構師或外部諮詢師,來完成這個事情。出了問題就不用本身來承擔責任了。這樣雖然是解決問題的一種折中辦法,但可讓事情毫無風險的執行下去。但這是一種短時間效應,沒法解決組織自己的創新窘境,長期依賴外部力量來解決最有價值的問題不會讓本身提高,反而造成了對外部力量的依賴。對於組織的凝聚力來講不是一件好事。

只有打破當前的工做習慣和思惟定勢,充分認識到創新的困難、風險以及價值的組織才能夠佔領創新的高點,吸引人才。

難點4:微服務技術棧的「選擇困難症「

因爲「精英主義」的架構師須要擔負很大的責任並承擔着很重的壓力。他們必需要爲微服務架構謹慎的選擇技術棧。所以會在不一樣的技術棧之間不斷嘗試。對於習慣了在大型研發組織裏「精心設計,加班生產」的架構師而言。「長設計,慢反饋」節奏彷佛是理所應當的。

微服務開源社區的快速發展助長了「架構師焦慮」:若是採用落後的技術會被同行鄙視,被不懂技術的老闆鄙視,甚至被下屬鄙視。所以架構師們疲於在各類新型的技術棧之間比較和學習。此外,不熟悉技術每每會增大風險,架構師就須要更多的時間研究。帶着「一步到位」的架構幻想對微服務技術棧精挑細選。而不會採用現有低成本的方案快速迭代的解決問題。

微服務的核心在於採用「小規模,快反饋」的機制下降軟件系統的複雜性並經過虛擬和自動化技術分散風險,從而能夠快速麪對市場變化帶來的各類挑戰,並可以快速銷售創新,得到市場的反饋。而不只僅是利用到了時下新興的語言,編程框架或工具。

學習和實踐是相輔相成的過程,在實踐的時候學習,並把學習到的知識應用到實踐中。而不是準備一場考試,先停下來學習,準備好了再盡心盡力。

以上四點會讓大型組織面對微服務實施的時候「卡殼」,而這每每會致使微服務實施容易忽略的最重要一點,我認爲也是核心的一點:

難點5:對微服務的技術變革估計太高,而對微服務帶來的組織變革估計嚴重不足

做爲架構師,永遠要不要低估康威定理的威力: 「設計系統的組織,其產生的設計和架構等價於組織間的溝通結構。」

從制度經濟學角度上講,軟件產品自己就是企業內部組織(員工)和外部組織(用戶)溝通制度的計算機程序表達。這個制度的發展必定是在不斷縮小內部組織之間以及內外部組織溝通成本的。

所以,系統的架構必定是和組織的架構相吻合的,若是不吻合,勢必會帶來問題阻礙組織的漸進。

這就引出了一個推論:若是企業組織的架構不是惟一的,那麼微服務的架構方案也不是惟一的。

當架構和組織結構相一致的時候,一切都會很順暢。反之,就會出現各類問題。

這個關係就像鞋和腳的關係,只有穿上合適的鞋,走起路來纔會舒服。過大太小的鞋都不會讓你加快前進的步伐。固然,你能夠選擇買鞋(引入產品),雖然並非很合腳,但還能夠湊合穿。可是在換鞋的時候你不得不停下來試。你也能夠花高價爲本身定製一套,只不過,這個不會讓你走得更快,只會愈來癒合腳。

若是全部人穿上了新鞋,都能跑得很快。那麼這就不是鞋的問題,而是你腳的問題,這就不是換鞋能解決的了。你得先把腳的問題解決了,而後再看鞋的問題。固然,也能夠經過鞋來矯正腳,只不過會花些功夫,但必定會比不停的換鞋更加有效。

很不幸,大多數的組織並無準備好迎接微服務架構帶來的組織變化。仍然把「系統架構問題」和「組織問題」割裂成兩個不一樣領域的問題:微服務是技術問題,組織問題是管理問題。

有競爭力的組織,是一個經過融合優點達到 1+1> 2 的組織。而不是把優點割裂開,獲得 1 + 1 <= 2 的組織。所以,技術問題和管理問題並非兩個問題,而是同一個問題的兩個側面。

所以,若是你的組織結構是去中心化的小團隊結構,那麼不用擔憂,你的應用架構會朝組織架構的方向演進。反之,若是你不是一個去中心化的小團隊結構,那麼微服務的架構會和組織架構格格不入。

那麼,如何高效的推進微服務架構演進呢?

若是以上 5 點都讓你膝蓋中箭。那麼根據我我的的經驗,綜合解決微服務實施難點的第一步就是:

步驟1:以終爲始,先構建一個獨立的敏捷微服務團隊

咱們對微服務的期待就是:能夠獨立開發,獨立部署,獨立發佈,而且去中心化管理。那麼,咱們就先構造一隻「能夠獨立開發,獨立部署,而且去中心化管理」的團隊。

這個團隊爲了達到這個目標,會採起各類方法(例如:DevOps,全功能團隊)解決阻礙」獨立開發,獨立部署,獨立發佈 和 去中心化的問題。而根據康威定理,系統的架構會慢慢向去中心化方向發展。

必定要意識到,這個過程會打破大型系統自上而下的既有流程並採用更有生產力的方式構建新的組織結構。你索要作的就是要充分信任團隊,把它看作是一個微型的技術管理創新。不要用老的方式控制團隊的運做,這會打擊團隊的士氣。

管理建議

  1. 讓微服務團隊徹底脫離以前的工做,專心於微服務的工做中。若是分心同時作幾件事,每件事都不會作到最好。
  2. 給微服務團隊一些特權,爲了知足「全功能微服務團隊的」訴求,特事特辦。
  3. 若是團隊在執行的過程出現了依賴從而阻礙了進度。則須要把依賴標明出來。代碼中的依賴容易看見,但組織中的流程依賴很難發現。
  4. 爲了不團隊對外部的「依賴慣性」,讓團隊本身想辦法在內部解決依賴。
  5. 組織流程的改變也是很重要的微服務架構產物,而不只僅是微服務代碼或基礎設施。

技術建議

  1. 爲微服務創建一個全新的代碼庫,而不要從原先的代碼庫上克隆或者複製,避免和原團隊的開發依賴。
  2. 建設一個獨立的持續交付流水線,最好是經過「流水線即代碼技術」(例如 Jenkinsfile)來自動生成流水線。

步驟2:構建微服務的「電梯演講」

成立了微服務團隊以後,接下來就是要選擇第一個實現的微服務。可是這個微服務應該多大,邊界在哪是個問題。這不須要進行嚴格的設計和反覆的論證,只要發現當前的痛點或者想要完成一個假設就足夠上路了。讓整個過程變輕,而不是變重。

個人建議是經過「微服務電梯演講」的方式來定義微服務。格式能夠是:

(XX微服務)用來

在(出現痛點的場景)的狀況下

解決了(解決現有的某個問題)

從而(達到什麼樣的效果)

提高了(微服務的價值)

例如:

(訂單查詢微服務)用來

在(訂單查詢數量快速)的狀況下

解決了(訪問數量迅速升高致使總體應用性能降低的問題)

從而(分離了訂單查詢請求)

提高了(提高了其餘功能的性能)

當構造了微服務的電梯演講,團隊就能夠以此爲原則啓動了。當碰到和現有系統衝突的問題,替換幾個詞比較有幫助你作決策。(語言必定程度上也是具備魔力的)

把「拆分」換成「移除」。例如:「從現有系統中拆分出訂單查詢功能」 轉變爲 」從現有系統中移除訂單查詢功能「。思惟方式就從一個團隊負責兩個系統變成了兩個團隊負責兩個系統。

把「集成」換成「調用」。例如:」用戶註冊和用戶登陸須要集成」轉變爲「用戶登陸服務須要調用用戶註冊服務的信息」。思惟方式就把兩個系統的關係更精確了,從而明確了微服務之間的關係和溝通方式。

管理建議:

  1. 把微服務的電梯演講打印出來掛到牆上,讓團隊成員銘記於心。這會強化組織對微服務的邊界認識。
  2. 隨着團隊的反思和學習,電梯演講有可能會變動,但必定要讓團隊造成共識好和一致的意見。
  3. 不要指望一次就能劃分正確。劃分是一個持續權衡取捨的過程。

技術建議:

  1. 明確了微服務的職責和邊界以後再去看代碼,不然會被代碼的複雜度影響。
  2. 領域驅動設計(DDD)能夠幫助你更好的劃分微服務。領域驅動設計很好的遵循了「關注點分離」(Separation of concerns,SOC)的原則,提出了更成熟、清晰的分層架構。
  3. 不會領域驅動設計(DDD)也沒有關係。簡單的使用「關注點分離原則」也能夠幫你達到這一點。例如:從接口中分離出流量較大的接口獨立部署,把讀數據庫和寫數據庫的 API 分開獨立部署,把靜態和動態訪問分離……等等。

步驟3:以最小的代價發佈出第一個微服務

要注意兩個關鍵點:一個是「最小的代價」,另外一個是「發佈」(Release)。

正如前文所述,微服務架構自己就覺了微服務必定是低成本低風險的漸進式演進。而最大的浪費在於:

1. 級別/職責分工明確的組織溝通結構

2. 「長時間,慢反饋」的行動習慣

3. 先進且學習成本較高的技術棧

所以,「最小的代價」包含了如下三個方面:

1. 最精簡的獨立敏捷全功能團隊

2. 最快的時間

3. 代價最小的技術棧

此外,不少微服務的「愛好者」因爲懼怕失敗,所以將微服務技術始終放在「實驗室」裏。要敢於面對失敗,在生產環境中面對真實的問題,但要採起一些規避風險的措施。

管理建議

  1. 儘可能讓現有微服務團隊本身學習解決問題,成爲全功能團隊。如無必要,毫不增添新的人手。
  2. 「扯破嗓子不如甩開膀子」,先動起來,在前進中解決問題。
  3. 先考慮最後如何發佈,根據發佈流程倒推。

技術建議

  1. 根據當前技術採用的狀況選擇代價較小的技術棧。
  2. 採用動態特性開關(Feature Toggle),在發佈後能夠在生產環境動態的控制微服務的啓用,下降失敗風險。
  3. 若是採用了特性開關,必定要設立刪除特性開關和對應舊代碼的時間,通常不超過兩個月。不然後面大量的特性開關會帶來管理成本的提高和代碼的凌亂。
  4. 因爲團隊比較小,功能比較單一,不建議採用分支來構建微服務,而應該採用單主幹方式開發。

步驟4:取得快速勝利(Quick wins),演示(Showcase)驅動開發

剛開始進行微服務改造的時候必定會是一個試錯的過程。若是目標定得太大,會讓團隊倍感壓力,從而士氣低落。而制定每日的短時間目標,贏得快速勝利則會不斷激勵團隊的士氣。經過設定當天結束的產出來肯定今天須要作什麼是一個很是有效的辦法。

每日演示(Daily Showcase)就是一種推動產出的作法。天天向團隊分享今天的工做內容,使小組可以共同窗習。而且以當天或者明天的 showcase 做爲目標。每一個人showcase 的內容通常不超過20分鐘,一天的 showcase 時間不超過一小時。能夠早上 showcase,也能夠下班後 showcase。

常見的快速勝利目標以下:

  1. 構造第一條微服務流水線。
  2. 上線第一個微服務 HelloWorld。
  3. 構造出第一個微服務自動化測試。

而如下的目標不適合做爲快速勝利的目標:

  1. 構造出微服務 DevOps 平臺。
  2. 完成整個產品的微服務架構拆分。
  3. 構造微服務自動化運維體系。

管理建議:

  1. 要防止團隊畫大餅,完成好每日和每週的工做目標便可。微服務開發自己就沒有很長週期。
  2. 強迫團隊有所產出,這樣才能用關鍵產出驅動開發。產出不必定是代碼或者基礎設施,一篇總結,或者學習的文章分享,甚至是踩過的坑和遇到的問題均可以展現,目的是要打造自治學習的團隊。
  3. 貴在堅持,不要計劃太遠。超過一個月,就要對目標是否是範圍過大進行反思。
  4. 以天爲單位拆分任務,超過一天的必需要拆分。沒法在一天完成的工做須要拆分出階段性產出。
  5. 若是能結對,而且可以天天交換結對,showcase 沒必要要。
  6. 可視化全部任務,用敏捷看板來管理任務是瞭解現狀的最好方式。

技術建議:

  1. 除了讓第一個 HelloWord 微服務儘快發佈到生產環境,其它的不要想太多。
  2. 完成了 HelloWord 的發佈,而後要考慮如何對發佈流程進行改進。而不是上線業務。

步驟5:代碼未動,DevOps 先行

微服務解耦的本質是把代碼內部的複雜性經過一些工具轉化外部複雜性。把代碼內部的複雜性分散到各個微服務中以下降總體複雜性和架構風險。在這個過程當中會大量採用了 DevOps 技術和工具。也能夠說,微服務是 DevOps 文化和技術在走到極致的必然結果。

以 J2EE 的應用爲例,之前Web Server + App Server + MiddleWare + Database 的傳統架構被代碼更少,更多的基礎設施工具所取代。由於基礎設施相對於代碼來講更加穩定,更加利於擴展。

我把微服務的技術架構問題比做「搭臺唱戲」:首先須要創建好微服務交付和運行的平臺,而後讓微服務上臺「唱戲」。

這個平臺一開始不須要很完善,只須要知足生產上線的必要要求便可。而在不少企業裏,這個部分是由 Ops 團隊在交付流程的末尾把關的。所以,把最後一道關卡的確認工做放到最前面考慮能夠減小後期的返工以及沒必要要的浪費。

之前,軟件的開發和測試過程是分開的。然而,隨着 DevOps 運動的興起和各類自動化運維工具的興起,這之間的必要性不如從前,只要有足夠的自動化測試作質量保證,就能夠很快的將微服務快速部署和發佈到生產環境上。

最開始的時候,哪怕是發佈一個 Hello World 程序,都代表微服務的持續交付和運行的平臺已經搭建好,微服務交付流程已經打通,這一點是重中之重。

從技術交付產物來講,DevOps 主要交付兩點:

  1. 持續交付流水線。
  2. 微服務運行平臺。

爲了保證微服務交付的高效,須要把這兩者經過自動化的方式有機的結合起來,而不是各爲其主。讓開發和運維的矛盾變成「自動化的開發運維矛盾」

此外,DevOps 指的不光是一系列技術,更是一種工做方式。從團隊工做方式來講,DevOps 要作到:

  1. 要讓 Dev 和 Ops 共同參與決策,設計,實現和維護。
  2. 團隊徹底獨立自主,打破對現有流程的依賴。
  3. 不斷的追求改進,讓團隊行程改進的團隊文化。

管理建議:

  1. 給團隊繼續前進最大的動力就是新程序快速投入生產。
  2. 若是你的組織是 Dev 和 Ops 分離的組織,先諮詢一下 Ops 工程師的意見。最好是可以給微服務團隊裏面配備一名 Ops 工程師。
  3. 若是不具有實施 DevOps 的條件,微服務架構就要從運維側,而不是開發側開始進行。

技術建議:

  1. 微服務的平臺一開始能夠很簡單,能夠之後慢慢加強和擴展。可是必定要部署到生產環境裏使用。
  2. 若是想使用現成的微服務平臺能夠參考 Spring Cloud。
  3. 微服務運行平臺能夠經過反向代理和生產環境並行運行。
  4. 採用灰度發佈技術在生產環境中逐步提高微服務的使用佔比。
  5. 基礎設施即代碼是 DevOps 核心實踐,能夠幫助開發人員迅速在本機構建生產環境類似的開發環境,減小環境的不一致性。能夠採用 Docker,Ansible,Vagrant 等工具來完成。
  6. 基礎設施對微服務應該是透明的。微服務不該該也不必知道運行環境的細節。只要可以正常啓動並執行業務就完成了它的任務。所以,基礎設施代碼要和微服務業務代碼分開,且微服務不該該告訴平臺本身如何部署。
  7. 服務註冊和發現是微服務架構的核心部分。consul 和 Eureka 是這方面的佼佼者。
  8. 部署(Deploy)和發佈(Release)要分開。

步驟6:除了提交代碼和發佈,微服務平臺一切都應當自動化

在完成了微服務的基礎設施和交付流程以後,就能夠開始實現微服務的業務了。這時候須要依據電梯演講劃分出來的微服務進行業務邏輯的開發。在以 DevOps 的方式工做一段時間以後,團隊應該養成了一些自動化的習慣,若是沒有,就應該檢查一下本身的自動化程度。最佳的自動糊理想的狀態就是除了代碼提交和發佈。在這之間的每個流程和環節都應當由自動化的手段來完成。

固然,也有不能自動化的部分。根據個人經驗,不能自動化的緣由主要來自於流程管理的制度要求,而非技術困難。這每每是組織沒有依據微服務進行流程變革致使的。這時候須要反省不能自動化的部分是否是有存在的必要。

另外一方面,雖然自動化能夠大量縮短微服務交付時間,提高微服務交付效率。可是自動化的同時須要考慮到安全因素和風險,不能顧此失彼。對於生產來講,可用性和安全性是最重要的部分。

關鍵的自動化:

  • 自動化功能性測試(UI/集成/單元/迴歸)
  • 自動化構建
  • 自動化部署
  • 自動化性能測試
  • 自動化安全掃描

管理建議:

  1. 鼓勵團隊成員自發的進行自動化的改進,這會給將來微服務批量開發帶來不少裨益。
  2. 不要一開始就追求全面的自動化,自動化須要花費必定時間。根據團隊的進度視狀況適度進行。

技術建議:

  1. 採用 TDD 的方式開發不光能夠提高質量,也完成了測試的自動化。
  2. 注意自動化的安全隱患。機密信息須要獨立管理。
  3. 關鍵步驟須要準備自動手動兩種方式,必要時能夠干預自動過程。
  4. 採用 git 的 hook 技術,在代碼 push 以前就能夠完成測試和靜態檢查,提高 CI 的成功率。

步驟7:總結並複製成功經驗,創建起微服務交付的節奏

當完成了第一個微服務,不要着急開始進行下一個微服務的開發。而是須要進行一次關於可複製經驗的總結,識別微服務開發中的經驗教訓並總結成可複製的經驗和產出。

如下是一些須要總結出來的關鍵產出:

  1. 微服務開發到發佈的端到端流程規範。
  2. 微服務開發的技術質量規範。
  3. 團隊合做中的堅持的最佳實踐。
  4. 常見技術問題總結。

有了以上的關鍵產出,就能夠對微服務開發團隊進行擴張。這時候有了微服務開發的老司機,帶着剛加入的同事一塊兒開發,風險會相對低不少。

管理建議:

  1. 剛開始的時候能夠每週進行一個回顧會議,團隊須要快速的反饋和調整。
  2. 不要急於擴張團隊,要在成功經驗穩定並造成模式以後再快速擴充。
  3. 避免微服務良好的開發氛圍被稀釋,剛開始的時候擴充團隊能夠慢一點。新老成員的配比不要超過1:1。
  4. 雖然微服務平臺趨於穩定,但在微服務沒有上規模以前,不要讓團隊裏缺乏 Ops 成員。
  5. 注意知識的傳遞和人員的培養。

技術建議:

  1. 不要急於在微服務應用規模不大的時候造成微服務模板,不然會限制將來微服務的開發和擴展。
  2. 在微服務不成規模的時候不要放鬆對微服務平臺的改進。

參考書目

《微服務設計》 是一本微服務各個方面技術的綜合參考材料。若是你在實施微服務的過程當中碰到了問題,它就是一個解決方案的分類彙總。

《持續交付》聚集了不少交付最佳實踐,當你的微服務實施碰到阻礙時,裏面的建議可以讓你解決當前的困境。

《領域驅動設計》和《實現領域驅動設計》爲拆分微服務提供了方法論,當團隊之間對於微服務的拆分有困難的時候,採用領域驅動的方法每每會獲得更好的效果。·

《微服務架構與實踐》是一本快速啓動微服務的工具和實踐的總結,可以幫助微服務入門者快速跨越門檻。


實錄:《顧宇:微服務架構高效推動實戰解析》


這裏寫圖片描述

相關文章
相關標籤/搜索