作者丨Aphinya Dechalert
編譯丨千山
曾幾何時,我記得我的手指瘋狂地敲打鍵盤,與龐大而雜亂的代碼庫搏斗。那是巨石的時代,代碼就像古老的城堡一樣,由一塊塊石頭砌成一個令人印象深刻的龐然大物。
幾年過去了,時代變了。開發人員口中的流行語變成了“微服務”。微服務革命——承諾成為我們的救世主。
我們被告知,通過將龐然大物分割成更小、自包含的獨立服務,我們將獲得無與倫比的可擴展性、敏捷性和可維護性。這聽起來是如此完美。
更快的部署?√
單獨擴展?√
獨立團隊開發?√
但是,當我把單體架構切換成微服務時,我不禁想知道:微服務的魅力真的像它所描述的那樣嗎?還是只存在于遠景的海市蜃樓,只有當我們走近時才顯露出它的挑戰?
1、微服務的誘人承諾
還記得我們不得不與多個團隊協調只是為了進行微小的調整嗎?傳統的單體架構是后勤方面的噩夢。
每次更改都需要理解代碼庫的大部分區域,與其他團隊同步,并希望一個小的調整不會引發多米諾骨牌效應。
但微服務打開了新大門:突然之間,團隊可以獨立開發他們的服務了。
例如,用戶管理團隊可以實施新的身份驗證策略,而無需等待庫存管理團隊更新其產品列表方法。這種解耦不僅僅是在代碼層面,它還延伸到了團隊動態。
O'Reilly 的一項調查發現,采用微服務的組織在團隊協作方面提高了63%。每個開發人員都成為其領域的大師(從字面上看,考慮到領域驅動設計實踐)。
在我們之前的一個項目中,我記得“黑色星期五”大促銷活動時引發的混亂。我們的單體應用難以應對大量涌入的用戶,導致所有功能的性能下降,而不僅僅是結帳流程。
微服務很好地解決了這種不平衡的需求。你只需簡單地在負載下擴展服務,而無需為整個應用程序過度配置資源。
想結賬的用戶激增?沒問題,擴大結帳服務規模。
宣傳視頻病毒式傳播?沒問題,提升媒體服務,不影響觸及其他服務。
思科的一項案例研究顯示,使用相同數量的資源的情況下,使用微服務架構設計的應用程序可以處理多達 20%的負載。
2、不那么迷人的現實
雖然許多人認為微服務是解決軟件開發問題的靈丹妙藥,但作為一名遠程開發人員,我對這種架構風格的嘗試經常感覺像打開了潘多拉的盒子。
在虛擬茶水間的閑聊和一行行代碼之外,這個故事總是充斥著無數希望、頻繁的正面交鋒以及相當多的啟示。
當我將我的第一個項目過渡到微服務時,我突然意識到,將一個應用程序拆分為多個服務并不是簡單的“分而治之”。
隨著拆分而來的是管理這些離散服務的責任。有一次,我部署了一個新的微服務,突然間,系統的其他部分失去了對它的跟蹤——這是分布式系統中服務發現(Service Discovery)的臭名昭著的挑戰。
此外,數據一致性也成為一場艱苦的戰斗。
我再也不能依靠單個數據庫事務來確保一切正常。因為每個服務都在管理自己的數據,我發現自己陷入了分布式事務的泥潭之中。
然后是失敗。當一項服務失敗時,連鎖反應通常會導致其他服務發生級聯故障。
理論上讓服務進行通信,聽起來很簡單。
但問題是:分布式系統引入了延遲。
一天晚上,我正在調試一個異常緩慢的操作,卻意識到罪魁禍首是服務之間的大量同步調用。等待下一個請求的次數增加了。
這需要改變戰略。
雖然通過事件進行異步通信減輕了一些痛苦,但它也帶來了挑戰,例如確保事件的順序。
被吹捧的模塊化承諾往往與性能相悖。雖然微服務可以簡化流程,但與傳統的單體應用相比,它們也可能導致通信延遲。
3、噩夢循環:部署混亂
作為 CI/CD 的堅定倡導者,部署單個服務的承諾感覺就像一個夢。
但現實很不一樣。最初的幾天尤其混亂。
使用多個管道時,一個服務中的更改有時需要與其他服務進行協調。還記得你每天都為之頭疼的版本兼容性問題嗎?有了微服務,跟蹤哪個版本的服務A與服務B兼容成為了一種日常儀式。
4、我開始懷念單體架構了
帶有一系列服務和數據庫陣列的微服務,常常感覺就像一塊不斷移動的拼圖。有很多個晚上,我發現自己由于無法預見的集成問題而恢復代碼,或者梳理日志試圖找到哪個服務是薄弱環節。
與巨石時代形成鮮明對比的是,在鐵板一塊時,變化盡管規模較大,但具有一定的可預測性。
工作流程是線性的,那么部署呢?好吧,他們感覺更受控制了。
如果你曾經嘗試通過一串 Slack 消息來傳達一個復雜的想法,你就會欣賞直接溝通的益處。與此類似的,在單體架構中,模塊之間的進程內通信的簡單性是直接、無縫的,并且通常被認為是理所當然的。沒有網絡調用,沒有延遲,沒有丟失請求。一切都在應用程序的范圍內正常工作。
使用微服務,服務間通信感覺就像試圖與分布在各大洲的團隊成員進行 Discord 語音聊天,每個人都在與自己的互聯網困境作斗爭。
當然,這是可行的,但這些小問題會讓你懷念一切都在一個屋檐下的時光。當公司要求他們的開發人員回辦公室坐班時,我理解了:它確實有它的好處,尤其是在即時溝通方面。
5、權衡:我們得到了什么,失去了什么
微服務的主要優勢之一是能夠專注于特定的功能。我記得我被分配到一個專門負責用戶身份驗證的團隊。解耦的特性使我們能夠完善機器中的一個齒輪。
不久前,我們的單體應用中的一個小模塊故障導致了嚴重的中斷。對于微服務,每個服務都充當其隔離的故障點。我見過一些特定微服務出現宕機的實例,但多虧了架構,整個應用程序得以繼續運行,用戶對此幾乎沒有感知。
6、當單體更好時
管理微服務感覺就像同時處理十幾個Slack頻道。每個服務都有自己的日志記錄、監視和部署過程。相比之下,單體架構有一個固定的流程。
微服務通常意味著多個數據庫。雖然這看起來很棒,但確保數據一致性卻是一場噩夢。在單體架構時代,一個數據庫意味著一致性。這就像在 Discord 中有一個線程,每個人都在更新。我經常發現自己懷念這種統一性提供的便利。
然后是整體調試。
還記得嘗試通過相互連接的微服務跟蹤bug嗎?這就像追溯無數的 Discord 對話來找到一條消息。但在單體架構的設置中,錯誤日志是集中的,因果關系更加清晰。
7、總結:微服務之旅中的反思
當我回顧自己在微服務領域的嘗試時,我發現這條道路充滿了挑戰、得失和可以從中學習收獲的寶藏。以下是我在微服務之旅中獲得的3個主要收獲。
1) 明智地接受復雜性
深入微服務不僅僅是一個技術決策——這是對復雜性的承諾。有時,我們會覺得自己只是為了順應潮流而打破了一個體系。并非每個應用程序都需要由相互連接的服務組成的網絡。正如Sam Newman在《構建微服務》中提到的那樣,架構需要一定的先決條件,如果沒有這些先決條件,它可能會矯枉過正。
2)靈活性是有代價的
是的,微服務承諾了靈活性,但要實現這一點,也需要付出沉重的代價——不僅在基礎設施方面,而且在認知負荷方面。每項服務都有自己的領域,需要專門的關注。
3)沒有放之四海而皆準的方法
架構決策不能脫離業務需求。靈活的初創公司的需求與傳統的企業應用程序截然不同。雖然經典案例研究(例如.NETflix 著名的微服務轉型)很有啟發性,但必須認識到,適用于一個人的方法不一定適用于所有人。
變身為技術弄潮兒可能很誘人。成為科技領域重大變革的組成部分有一定的吸引力。但作為代碼的守門人,我們需要抵制盲目接受趨勢的誘惑。批判性評估、理解趨勢背后的“原因”,并權衡其與我們的特定背景的相關性至關重要。
Slack 消息、Github 存儲庫和 Discord 討論已成為我們許多遠程開發人員的新飲水機。在各種噪聲中,讓我們記住定期聚焦,反思我們的選擇,并確保我們不只是追逐趨勢,而是有目的地制定經得起時間考驗的解決方案。
參考鏈接:https://medium.com/@PurpleGreenLemon/was-microservices-a-bad-idea-5e52edee1cff