Segment 微服務反水案的一點思考

2015 年底,Segment 博客刊登了一篇文章,Why Microservices Work For Us(下文簡稱為《Work》),三年多,又來了一篇更具話題性的新作:Goodbye Microservices: From 100s of problem children to 1 superstar(下文簡稱為《Bye》),兩相比較,感覺還是有一定的代表性的,這裡做一點整理和記錄。

微服務的動機

《Work》中提到,主要是因為原有架構中,故障處理不力,需要有更快的診斷和處理方法,這裡提到了兩個途徑:

  • 問題的快速定位:藉助更細緻方便的監控指標,為突發事件提供明確指導。
  • 問題的快速解決:在定位問題之後,能夠更好的從源碼中獲得支持並解決問題。

要針對某個功能加入監控指標,在原有單體架構中可能會造成不必要的影響,範圍不易控制;而源碼方面,越小的服務,通常也代表著相對易讀的代碼;這兩個主要需求都指向了同樣的解決方案:微服務。

微服務帶來的好處

將原有單體應用拆分為微服務之後,不但解決了監控和排錯的問題,還帶來了一些額外的好處:

  • 隔離的消息隊列,不同訂閱互不干涉
  • 隔離系統資源,如 CPU 和內存。
  • 隔離網絡,如 ELB。

這裡只是原文中提到的好處,更多的照本宣科內容這裡就不贅述了。

改造的隱憂

《Work》一文中提到了兩次,新建微服務應該如何如何。作者似乎認為,微服務有必要更快的創建起來。但按照我的理解,微服務僅是通過進程隔離的強制手段使得模塊之間的邊界更加清晰,事實上,因為缺乏單體應用強大的上下文支持,同一系統內的不同微服務,往往會因為上下文問題,導致更加複雜的開發過程。

《Bye》一文中補充的拆分過程

  • 單代碼庫階段
  • 因為缺乏有效的時間說明,這一操作讓人很迷惑,不知道是不是在《Work》發表的時候,各個服務還是在共用同一套代碼。也在共用同一套測試方案。《Bye》中提到,一個失敗的提交會導致整體測試失敗,因此我們大致可以說,這一階段裡,CI/CD 過程也沒能完成分割,個人認為,這種情況不太應該算作微服務。
  • 多代碼庫階段
  • 為微服務獨立創建各自的代碼庫,並享用各自的測試組件。
  • 共享庫階段
  • 我認為這一階段呼應了前面的隱憂,在微服務落地之處,為了更快的建立微服務,開始出現了跨服務的共享代碼庫。

敗局的開始

《Bye》的共享代碼庫一節,羅列了不少遇到的問題:

  • 共享庫版本出現碎片:因為工程需要,並不敢冒險同時更新的多個服務的共享代碼,造成部分服務的共享代碼滯後。
  • 伸縮能力:微服務架構經常鼓吹的能力,在這裡似乎被狠狠抽了一巴掌。

個人的一點分析

我眼中的微服務,務虛的角度上來說,有兩個關鍵字:妥協,懷疑。

這裡所說的妥協指的是,我們的系統是存活於一個非“理想狀態”中的,不管是“擁抱變化”,還是“面向故障”,都是對不完美世界的具體應對方式。

而懷疑的設計態度,最簡單的證據就是對隔離的強調,系統資源、數據的隔離都如此強調,我想,代碼的隔離是不言自明的。

反觀 Segement 的重構之路,(可能)在宣稱微服務的時候,各個服務還躺在同一個倉庫裡,還在共享同樣的測試過程。

在進行代碼分離之後,又出現了兩個不太容易理解的紕漏:

  • 曖昧的代碼:前面提到,懷疑是微服務的基本態度,從《Bye》文中可以看到,他們在幾十個服務之間共享了需要進行頻繁重構的代碼,拋開微服務和單體之爭不談,這個行為實在是無法理喻。
  • 曖昧的負載:在拆分之後,按照《Work》的說法,每個微服務都有了獨立的隊列和監控,由此推論,各個微服務的負載模型應該是比較容易做個描述的,很可惜的,這裡稱之為一種藝術。

回到單體之後

此處內容給人一種感覺:“今天是個好日子”。給我的感覺是,一些原本應該在微服務階段完成的工作,甚至是在微服務階段之前的單體階段完成的工作,終於完成了——例如改進的測試方案,這能算是半渡而擊麼?

牢騷

流水賬寫到這裡,有兩個深刻的印象就是,這個團隊從來沒想過這些微服務是彼此獨立的,也從來沒把每個服務作為一個單獨的交付物進行完善。從這個印象出發,回到單體形態,可以說是——得其所哉。


分享到:


相關文章: