為什么微服務實施那么難
難點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. 在微服務不成規模的時候不要放松對微服務平臺的改進。
-
微服務
+關注
關注
0文章
137瀏覽量
7341
發布評論請先 登錄
相關推薦
評論