撰稿 | 杰承
51CTO讀者成長計劃社群招募,咨詢小助手(微信號:CTOjishuzhan)
眾所周知,身為全球“云計算一哥”,亞馬遜向來是微服務和無服務器架構的追捧者。長期以來,亞馬遜也在眾多場合表示過對這種“現代化”應用程序最佳構建方式的支持。
然而作為亞馬遜旗下元老級別的流媒體平臺,Prime Video卻在近期發表的一篇博客中否認了老大的這一觀點,并提出了“從分布式微服務架構到單體應用的轉變,更有助于實現高規模、彈性和降低成本。”
Prime Video的這翻言論,其實都源于其技術團隊近期所進行的一項實踐——當團隊將Prime Video從微服務轉向整體應用后,不僅提升了其擴展能力,還成功節省了90%的基礎設施成本。
1、選擇微服務的初衷
作為一個流媒體平臺,Prime Video每天都會向客戶提供成千上萬的直播流。為了確保客戶無縫接收內容,Prime Video需要構建一個監控工具來識別客戶所查看的每個流中的質量問題,這提出了極高的可擴展性要求。
對此,Prime Video團隊優先考慮了微服務架構所能帶來的便利。由于微服務能夠將單體應用分解為多個模塊,這不僅能解決工具獨立開發和部署的問題,還能為應用提供更高的可用性、可靠性以及技術多樣性。
在經歷了上下的一致認可后,Prime Video選擇創建了一個由AWS Step Functions編排的分布式組件的解決方案,這是一個基于狀態機和任務的無服務器編排服務,理論上,這將允許團隊獨立擴展每個服務組件。
在完成一系列遷移工作后,Prime Video的服務最終由三個部分組成,媒體轉換器將音視頻流發送到檢測器的音視頻緩沖區;缺陷檢測器執行算法,并在發現缺陷時發送實時通知;第三個組件則提供控制服務流程的編排。
2、難以承受的系統開銷
但很快,Prime Video便意識到了分布式方法在特定用例中并沒有帶來很好的效果。最初的解決方案設計使用了無服務器組件的分布式系統,這在理論上而言是快速構建服務的最好選擇。
然而當更多流加入到服務中時,擴展受限和成本過高兩項問題開始逐漸顯現。該架構中的主要擴展瓶頸是使用AWS Step Functions實現的編排管理,由于服務每秒都會在流中執行多次狀態轉換,這使服務很快達到了賬戶限制。
除此之外,由于AWS Step按照函數狀態轉換向用戶收費,當需要處理大量流的時候,大規模運行基礎設施的開銷會變得非常昂貴,所有構建模塊的總成本過高,導致Prime Video團隊無法大規模接受最初的解決方案。
基于開銷問題,Prime Video為了減少昂貴視頻的轉換工作而建立了一個新的微服務,以將視頻分成幀并將圖像臨時上傳到亞馬遜簡單存儲服務(S3 Bucket),并使用AWS Lambda并行處理。然而對S3 Bucket的大量一級調用同樣需要支付巨額費用。
3、從微服務遷移到單體架構
無奈之下,Prime Video開始考慮單體的解決方案以降低成本和增加應用的擴展能力,在經歷了反復試驗后,團隊最終決定重建Prime Video的整個基礎設施。
當意識到分布式方法在特定用例中無法帶來更多好處時,Prime Video選擇將應用中的所有組件打包到一個流程中,這成功消除了S3 Bucket作為視頻幀中間存儲的需求。在此基礎上,團隊還實現了在單個實例中控制組件編排。
從概念上講,在保持頂層架構不變的前提下,Prime Video仍然擁有與初始設計完全相同的組件,包括媒體轉換器、缺陷檢測器及編排。這允許Prime Video團隊重用大量代碼,并快速遷移到新的架構。
當然,轉換為單體架構也給Prime Video提出了新的挑戰。在最初的設計中,由于每個檢測器都能作為獨立的微服務運行,Prime Video能夠水平擴展多個檢測器。然而在單體架構中,檢測器只能在同一實例中運行。
為克服這個問題,Prime Video對服務進行了多次克隆,利用不同的檢測器子集對每個副本進行參數化,并實現了在單個實例中控制組件的編排,該解決方案運行在EC2(彈性計算云)和ECS(彈性容器服務)上,且具有一個輕量級編排層來分發客戶請求。
最終,將全部服務遷移到整體平臺后,Prime Video的基礎設施成本降低了90%,并擁有了更強的擴展能力。如今,Prime Video不僅能夠同時處理成千上萬的音視頻流,且仍有能力進行更多的服務擴展。
4、被過度營銷的微服務
微服務被過度營銷可能是許多問題的根源,medium作者Adrian(前亞馬遜云科技可持續發展架構副總裁、前云架構戰略副總裁)發文認為,這可能是因為供應商想通過簡單的營銷信息來銷售Kubernetes,即企業需要通過使用Kubernete為一切提供云原生微服務來實現現代化。
事實上,我們看到的是對這種信息的實踐上的強烈反差。具有諷刺意味的是,許多企業工作負載是間歇性的、小規模的,非常適合使用Step Functions和Lambda的無服務器優先方法。但如果大型團隊則不然,大規模運行的成本是高昂的,僅Kubernetes的復雜性就會讓人倍感頭疼。
摘自Serverless First(無服務器優先)2019年發布
Prime Video團隊的做法被adrian稱之為Serverless First的路徑,即,構建東西的第一次嘗試是與Step Function和Lambda調用結合在一起。重點在于,當你在探索如何構建東西時,在幾天或幾周內快速構建一個原型是一個很好的方法。然后,他們試圖對其進行擴展,以應對高流量,并發現他們的步驟函數中的一些狀態轉換過于頻繁,并且他們在AWS lambda函數和S3之間進行了一些過多的調用。他們能夠重用大部分工作代碼,將其組合成一個長期運行的微服務,該微服務使用ECS進行水平擴展,并通過lambda函數調用。這只是構成Prime Video應用程序的眾多微服務之一。
問題是,他們將這種做法稱為微服務到單體的轉變,而這顯然,只不過是微服務重構的一步。
5、微服務不應該是默認選擇
這篇博客確實證實了一些開發者的懷疑,微服務相對于整體應用的優勢經常被夸大;微服務的解決方案也并非在所有情況下都是最具成本效益的,因為它們總是會涉及使用多種昂貴的服務。
在Hacker News中,Ruby on Rails之父Hansson給出了這樣的評價,“這篇文章理論上總結了一段時間以來席卷科技行業的微服務熱潮,現在,所有這些理論的實踐結果終于出現了。很明顯在具體情況下,微服務是可能導致你系統復雜化的最大誘因。”
按照Hansson的說法,“在一個單一的、一致的團隊和應用程序中,使用網絡調用和微服務劃分代替方法調用和模塊分離,在幾乎所有情況下都是非常瘋狂且沒有意義的,而無服務器會讓情況變得更糟。”
《構建微服務》一書的作者微服務大師Sam Newman也在Twitter總結了以下的觀點,“這篇文章更多的是在談論功能定價模型與長期運行虛擬機的定價模型,這是完全合乎邏輯的架構驅動因素。雖然這個案例所提供的經驗并沒有太廣泛的適用范圍,但當情況發生時,改變想法的確是非常明智的。”
總而言之,即使是作為單個進程或整體部署的應用程序,在設計上也是可以進行模塊化的,不同的團隊在每個模塊工作。實現了這一點,許多組織使用模塊化整體架構的效果將比微服務更好。微服務不應當成為組織的默認選擇,而應當是最后手段。
6、寫在最后
歸根結底,無論是微服務還是單體架構,都有著自身的優勢與缺陷。但在過去幾年中,太多的開發者被微服務的好處所說服并輕易對其進行了采用。這也導致了許多系統體量或是團隊成員不足的組織的失敗。換句話來說,當你沒有明確看到當前系統的瓶頸時,先做所有簡單的事情。
Prime Video的這篇博客對于許多支持分布式微服務的云巨頭而言并不一定是一個壞消息。雖然在一方面,它違背了云巨頭所傾向的最佳實踐;但在另一方面,它提供了一條令人耳目一新的道路,以及一個非常成功的遷移案例。與許多我們所熟知的促銷方式不同,這個案例可能對這些云巨頭的客戶而言將更有意義。