微服務的先決條件

banq發表於2017-06-18

Phil Calcado於2017年5月在布達佩斯的Craft Conf發表了關於Microservices幾個先決條件的演講,被分散式領域的其他作品紛紛引用,在本文中他詳細擴充套件論述了這些微服務的先決條件。下面是他的原文:

2017年5月,我在布達佩斯的Craft Conf發表了關於Microservices經濟學的演講。您可以在這裡觀看影片錄製或在這裡閱讀幻燈片。在這個演講中,簡要討論了一系列微服務提出的先決條件,這是我認為你在考慮廣泛採用微服務架構風格之前應該採取的措施。自從演講以來,這些措施列表已被分散式系統空間中的其他作品所引用,所以我想透過這個帖子來擴充套件這些先決條件。

為什麼會煩惱?
當您決定採用微伺服器時,您將明確地不僅僅是將一個或幾個移動的部件移至更復雜的系統。在這個新的世界中,許多運動部分以團隊不可預知的方式行事,因為服務會不斷創造,改變和消滅。該系統具有能夠快速更改和調整適應能力,可為您的組織帶來巨大的收益,但您需要確保有一些保護措施已經到位,否則您的交付可能在不斷變化的情況下停滯不前。

這些保護措施就是我們在這裡討論的先決條件。無視其中一部分或所有部分雖然可以也可以成功,但是它們的存在有望提高成功的可能性,並減少遷移過程中的噪音和混亂。

誠然,這裡列出的先決條件很長,根據您的組織的文化和基礎設施,可能需要大量投資。應該預期這個前期成本。微服務架構不應比其他風格更容易,您需要確定您在作出決定之前評估投資回報率。

真的是很多。我可以嘗試讓你放心,告訴你這些不是微服務的必需品,但除非你有一箇中型到大型的團1隊,否則我不認為你應該使用微服務。您應該以最簡單的方式開始您的架構,這樣可能會起作用。

您不需要對這裡提到的先決條件提供複雜甚至成熟的答案。即使在像DigitalOcean和SoundCloud這樣的成熟公司,我們也是一開始進行非常基本的實現。包括有很多的探索和通常的複製和貼上。

你應該確保你有關於這些列表問題有一個可行答案,但不要迷戀它們。你今天的答案不一定是長期的解決方案。隨著時間的推移,您將會學到更多的知識,同時技術空間也在逐漸成熟,其中一些技術已經成為現貨。

另一個選擇是忘記微服務,並將您的架構的下一個迭代集中在更粗糙的服務上。更少的可移動部件肯定會大大降低這些先決條件要求,隨著工程組織和平臺的成熟,您隨時可以減少服務的大小和範圍。

先決條件
正如我在前一段關於我們在SoundCloud中採用微服務的演講中所討論的,我非常感謝Martin Fowler在微服務先決條件方面的工作:

1.快速配置:你可在幾個小時內啟動一個新伺服器

2.基礎監控:使用很多這些松耦合的微服務,很難發現問題根源,因此監控是基礎的。

3.快速應用部署:管理這麼多服務,你應該能快速部署它們,無論測試環境或產品環境。


在Martin對微服務這些特點定義之前,SoundCloud已經開始向這種架構遷移,但是我們也得出了相同的結論。當我轉到我的第二個大型微服務實施時,這次是在DigitalOcean,我們再次證實了上述專案的需要。同時,我已經確定了一些其他缺少的專案,這些專案已被證明對於成功實施微型服務至關重要:

1.儲存易於配置
2.輕鬆訪問邊緣
4.認證/授權
5.標準化RPC

所以我的完整列表中的微服務先決條件按優先順序如下:

1.計算資源快速配置

2.基本監控

3.快速部署

4.儲存易於配置

5.輕鬆訪問邊緣

6.認證/授權

7.標準化RPC


1.快速配置計算資源

Martin馬丁說:

您可以在幾個小時內啟動新的伺服器。自然,這適合雲端計算,但如果沒有全面的雲服務,這也是可以實現的。為了能夠進行這種快速配置,您需要大量的自動化 - 它可能不需要完全自動化才能開始,但是以後要做出大量的微服務時,就需要這樣做。

他在這裡使用"伺服器servers"這個詞語,但是現在可以使用實際的伺服器,虛擬機器,容器,功能或所有這些功能的組合概念表達。這就是為什麼我新增了“計算資源”到這個專案,因為它幾乎意味著任何會執行你的程式碼的一些CPU和記憶體。

十多年前,我們曾經在應用伺服器上部署我們的服務和應用程式。這些是大量軟體層,複用了單個計算單元,以便許多應用程式和服務可以同時使用它,並且這種部署架構是多年的規範。當時,每秒服務幾百個請求被認為是Internet規模,這種設計允許組織最大限度地利用不同服務的昂貴硬體,有時甚至提供不同公司共享昂貴應用伺服器的多租戶服務。

[img index=1]

隨著時間的推移,計算資源的成本大大降低,無論是內部部署還是由雲提供。這減少了對應用伺服器層的需求。即使應用程式伺服器為部署在其上的應用程式(例如自動安全,服務發現,管理皮膚等)也提供了開箱即用的服務,但是會由此帶來操作這些更復雜的伺服器變得非常昂貴。最重要的是,隨著流量的增加,我們從垂直擴充套件到水平可伸縮性,這些產品從未得到很好的支援。

所有這些趨勢促使我們發展成當前使用的最常見的部署架構,其中服務例項與計算資源之間存在1:1的關係。

[img index=2]

這種1:1的關係直接影響微服務架構。如前所述,微服務術語還不是很明確,但有一點你可以絕對肯定,當有人說這句話的是,他們將有很多的小服務。鑑於上述部署架構,這也意味著您將擁有大量的計算單位。這就需要自動,快速,靈活地配置計算單元來滿足您的微服務需求。

當我在2015年加入DigitalOcean時,花了很多時間與我的團隊一起考慮了我們的內部系統,即雲的“控制面”。之後,它主要由三個不同的單體monolith組成,它們透過主資料包定義的一組固定的虛擬機器上執行。我們很快就清楚,這是一個複雜且容易出錯的工作流程,它不能擴充套件。在遷移到微服務之前,我們不得不改進這些配置情況。

負責解決這個問題的團隊決定使用容器和Kubernetes作為我們的新計算平臺,我們在2016年的頭六個月都確保所有新服務都部署在這個新系統上,並將舊版單體系統遷移到這個新系統。這一步使我們能夠繼續推進我們的架構變革,同時仍在努力解決我們不得不釋出的許多新產品。事實上,我們的監控和警報功能是在新系統中開發的第一個產品,並且是動態追蹤“子彈”的,整合了平臺團隊的後端很積壓的和優先的事項。


2.基本監測

馬丁說:

隨著許多鬆散耦合的服務在生產環境中合作,事情肯定會出現錯誤,這些在測試環境中難以發現。因此,必須建立一個監測制度,以迅速發現嚴重問題。這裡的基準是檢測技術問題(計數錯誤,服務可用性等),但也值得監控業務問題(例如檢測訂單下降)。如果突然出現問題,則需要確保您可以快速回滾,因此...

如上所述,微服務架構是一個複雜的系統。你可以控制和預測有很多。許多這種混亂是由不斷變化的狀態驅動的,因為服務每天部署和重新部署多次。

事實證明,這個問題並不是微服務的獨有之處。事實上,John Allspaw和其他人在為Flickr和Etsy開發單體架構同時,已經在近十年的時間內圍繞這些挑戰構建了一個工具箱。在他的工作中,Allspaw記錄了處理快節奏變化的關鍵因素:

換個方法:

MTTR(平均修復時間)比MTBF(平均故障間隔時間)更重要

(對於大多數型別的F)

我絕對不會說,失敗應該是可以接受的條件。我認為,由於失敗將會發生,它同樣重要(或在某些情況下更重要)花費時間和精力來應對失敗,而不是試圖阻止它。他同意哈蒙德所說:

如果你認為你可以防止失敗,那麼你就不會發展自己的反應能力。

平均故障間隔時間(MTBF)是操作期間系統故障之間經過的時間。平均修復時間(MTTR)是解決操作中的問題所需的平均時間。簡單來說,MTBF告訴您,故障發生的頻率如何,而MTTR告訴您一旦檢測到問題就能解決問題。在不斷變化的系統中,您無法控制MTBF,所以最好投資擁有一個偉大的MTTR。

當您開始投資減少MTTR時,您開始意識到這樣太頻繁。事件恢復並不是事件管理中唯一的一步,我一再看到事件管理中最痛苦的部分是平均檢測時間(MTTD)。此度量反映了事件發生與操作員檢測到的時間,從而觸發恢復過程。

這使您意識到您需要投資遙測來快速檢測問題。雖然這種需求存在於任何架構風格中,但微服務在這裡增加了一些不同的挑戰。在一個單體架構中,你總是知道問題出在哪裡:顯然是在單體之中!剩下的是找出問題所在的類或功能。在這個世界上,諸如NewRelic之類的複雜工具可以幫助您進入程式碼級別來檢測問題:

雖然這些工具也廣泛應用於微服務體系結構中,但是在檢測到哪些服務或服務以意想不到的方式執行後,它們才有用。由於許多服務相互協調呼叫才能完成每個請求,您還需要確保您可以將服務彼此進行比較,從而允許您精確定位異常值,而不會因環境問題而分心。

所以,您應該更喜歡整個微型服務的基本遙測,並透過多項核心服務的詳細遙測。

在SoundCloud,我們在微服務監控方面的經驗使我們專注於標準化儀表板和警報。我們確保每一個服務都以相同的粒度匯出一組通用的指標。然後,我們使用它們來構建儀表板,首先在Graphite上,最終在Prometheus上,允許我們在不同的服務之間比較這些指標。


儀表板為我們提供了減少MTTD所需的洞察力,但是我們很快意識到這還不夠。隨著數十個小型團隊部署了數十個服務,您需要能夠將潛在問題與變更相關聯,新程式碼部署和基礎設施更改。在我們的例子中,我們構建了一個小型Feed服務能夠反映工程師和自動化工具所做的所有更改。我們更改了我們的部署工具,以確保每一次更改,即使您只是透過新增一個或兩個其他例項來擴充套件服務,都能被報告給該Feed。

檢查任何最近的變化成為事件檢測工作流程的第一步。

3.快速部署

馬丁說:

管理許多服務,您需要能夠快速部署它們,無論是測試環境還是生產環境。通常這將涉及一個可以在不到幾個小時內執行的DeploymentPipeline。在早期階段,一些手動干預是好的,但是您將會盡快完成自動化。

馬丁提出這項是對前一項的直接跟進。他指出,事件的迅速恢復可能需要部署一些新的程式碼或配置,因為部署應儘可能快速和確定。

我完全同意這一點,但對我來說,另外一個基本的驅動因素是與事件響應沒有直接關係的前提條件。使用單體可以容忍有一個麻煩和非常手動的部署過程。容忍出現錯誤的風險,每次部署成本都高,因此通常每次部署通常都會包含許多變化,影響由不同的人和團隊開發出來的各種功能。

使用微服務,它變成另一個方面:對單個功能的單一更改可能需要部署許多服務。您將不得不執行不同服務的許多部署,重要的是這些部署中的每一個都是廉價的,風險很低。正如馬丁所說,建立管道往往適合這個方式。

這是我們在SoundCloud中最掙扎的先決條件。我們的單體使用Capistrano和shell指令碼部署在一個漫長而互動的過程中。包含有關如何執行部署的說明檔案都非常複雜,並且有許多角色通常被稱為tax_code.md。

正如我在SoundCloud的工程部落格中首次描述的那樣,一開始我們就決定我們的服務可以用任何語言和執行時。這個策略有幾個優點,但其中的缺點是我們無法對應用程式的部署做出假設。我們有.jar檔案,Ruby指令碼,Go二進位制檔案...一切。作為所有程式碼庫的最小公分母,我們將其標準化:

1. 每個服務都有一個Makefile位於服務程式碼目錄的根目錄下。這個指令碼有一個build目標,即使它所做的只是呼叫另一個構建系統,如SBT或Rake。

2.make命令完成後,部署工具將建立一個包含該目錄中所有內容的SquashFS偽像,包括程式碼,資產和生成的二進位制檔案。

3.程式碼還應該包含描述如何執行每個程式的Heroku樣式的procfile。在部署了SquashFS映像之後,操作員必須按照與Heroku相同的方式放大/縮小版本的程式。

這個過程允許我們擴充套件到十幾個服務,但是所需的手動步驟的數量太高,這導致了風險。更糟糕的是,這些較低階別的原語並不直接支援更有趣的部署技術,如藍色/綠色部署,金絲雀canary 伺服器,甚至是A / B測試。由於這些問題,大多數團隊最終在提供的工具之上建立了自己的膠水程式碼。由於這些指令碼被視為輔助專案,它們的程式碼質量差異很大。我們有一些由於缺陷指令碼導致的大量生產事故事件。

隨著我們從十幾個增長到接近一百個服務,我們為部署投入了更好的工具。最大的區別是我們從工程師的膝上型電腦中部署到建立管道(我們開始使用Jenkins,但最終轉移到ThoughtWorks的GoCD)。繁重的自動化導致了我們更多的確定性和更快速的構建,特別是當每天的部署次數從一個到數百個時,這就正是人們所需要的了。

易於配置儲存

大多數從單體到Microservices的公司將擁有一個單一,大型,維護良好的資料庫伺服器。經過多年的資料儲存,這個資料庫設定通常是很好的調整,有許多複製品,並且與其他系統(如搜尋引擎和資料分析工具)完美整合。

儘管如此,使用這個單體資料庫還有很多挑戰,其中大部分與架構更新有關。更改或刪除表和列需要手動確保沒有程式碼透過程式設計或超程式設計依賴於舊的結構。幾年之後,每個經典的資料庫重構已被應用到單體,而內部的工具已經被編寫為最常見的工具。

然而,採用微服務的團隊重新使用共享模式仍然很常見。“只有一個額外的表/列/檢視應該不會是一個大問題”,溫水煮青蛙。除了上述變化管理開銷之外,您的速度下降,您雖然遠離資料耦合卻在不同微服務之間JOIN耦合了(JOIN是資料庫SQL常用耦合語句),這些微服務本來不應該知道對方的內部細節的。

遷移到微服務主要方向是公司傾向於投入大量的配置和部署,但是忘記提供一個合理的方式讓儲存系統團隊可以依靠。即使玩轉MySQL伺服器只需要幾秒鐘,當將這些隔離的系統置於生產就緒時,也要注意到這幾秒鐘涉及到許多需要注意的專案。複製,備份,安全性,調優,遙測和其他幾個方面很重要,而且您的工程師經常在設定和擁有資料庫系統這兩個方面擁有零經驗。

如果您正在開展雲原生架構,許多資料庫即服務產品之一允許您將這些操作任務外包給供應商。在像DigitalOcean這樣的雲提供商,我們沒有這個選擇 - 我們是擁有電腦的臭名昭著的其他人。我們有一箇中期計劃,可以快速,輕鬆地提供MySQL資料庫供內部使用,但是第一步要解鎖我們向微服務的轉移,這一點要遠遠不夠雄心勃勃。我們投入了大量時間來清理和記錄標準化廚師食譜(比喻繁瑣細節)和相關指令碼,這樣可以使任何一個團隊都可以將生產級的MySQL伺服器升級到無需太多麻煩。


5.輕鬆訪問邊緣

公司中第一個微伺服器通常是孤立地寫成的,由單個人或小團隊開發作為解決他們遇到的一些挑戰比如業務功能需求等。因為這個服務的範圍通常很小,所以作者在開發和測試環境中得到一個能正常工作版本是很容易的。一旦接近生產階段,工程師面臨著一個問題:如何將這個新事物公開給我的外部使用者,我的本地網路以外的使用者?

與資料庫面臨的挑戰類似,這裡的主要問題是,在此之前,公司中沒有人必須考慮這個問題。單體架構是完全暴露給使用者的,可能是暴露給整個公共網際網路多年。它具有保護您的內部VPN免受惡意或錯誤使用者的所有功能。速率限制,日誌記錄,功能標誌,安全性,遙測,警報,請求路由...都在那裡。

由於某些原因,這個第一個微伺服器最常見的策略似乎是將其直接暴露給網際網路,無論是在不同的主機名或特殊路徑下。

該技術依賴於客戶端(通常是移動或單頁應用)將請求的多個端點的結果合併。這對於一個服務可以工作得很好,但隨著更多的服務被新增,該模型傾向於破壞。

不僅客戶端程式碼變得越來越複雜,而且在公共網際網路上暴露服務不是一件簡單的工作。如果您認真對待客戶和使用者,您需要確保面向網際網路的系統可以處理各種事件,從惡意使用者到意外的高峰流量。讓每一個單一的服務處理這一點大大增加了每個服務的成本。

我們需要限制一些服務暴露在網際網路上。我們考慮建立一個繫結所有服務的閘道器,但是透過小型工程團隊和大量產品遞交努力以後,我們發現需要一箇中間解決方案。

在我們的例子中,我們開始使用單體作為閘道器:

客戶端 ---->單體服務 ---->多個微服務


所以每個請求都將首先發到單體服務,然後在後臺呼叫其他服務。這個策略在接下來的幾個服務中執行良好,但有幾個問題。我們發現的第一個問題是,它在新服務和單體服務之間創造了一些奇怪的耦合,其中改變服務通常需要改變並重新部署單體。除此之外,我們的單體執行著一個非常老版本的Rails。沒有良好的併發性,我們不得不依靠對所有這些新服務的序列化請求。隨著我們新增的每項新服務,我們的請求時間都在增加。

隨著時間的推移,我們投資了一個正確的閘道器,這是在我們遷移到BFF模式的同時引入的。

客戶端 ----> Edge Gateway邊緣閘道器 ---->多個微服務 單體服務


我們在DigitalOcean採取了類似的道路,但是由於我們有三個單體而不是一個,遷移到邊緣閘道器不那麼容易。

6.認證/授權

這是另一個重要的組成部分,我們通常只想到第一個微伺服器接近生產時,微伺服器是如何知道誰在提出這個請求,以及他們擁有什麼樣的許可權?對這個問題的天真的方法是使每個微伺服器需要使用者識別符號作為對其的所有請求的一部分,然後根據您的使用者授權/認證系統或資料庫進行檢查。

當您有單體服務時,這可能足夠好,但是您會在授權系統中新增更多冗餘和昂貴的呼叫,隨著服務越多越是這樣。

在SoundCloud中,當我們使用單體作為邊緣閘道器時,我們已經在記憶體中瞭解有哪些使用者以及他們可以做什麼。我們更改了HTTP客戶端程式碼,始終將此資訊作為從單體到下游服務的所有HTTP請求的頭部中傳遞。

一旦我們遷移到邊緣閘道器,我們決定這個元件將向身份驗證服務發出一個請求,並且不僅向使用者URN轉發地理位置資訊和OAuth範圍,而且這些請求可以在每次向下遊服務發出的呼叫中提供 -在音樂行業,您被允許訪問的內容取決於您遇到的國家與您的身份相同。

[img index=3]

一旦我們將大多數內部服務遷移到基於Finagle的微服務的內部SDK中,這種更復雜的設定是可能的。

相關文章