实践中的弹性基础架构
幾周前,我獲得了一個難得的機會,可以在基礎設施領域弄臟雙手。 在JVM內部的深入了解下,我每天的工作經歷發生了有趣的變化,我想與您分享動機和成果。 希望它可以啟發類似的問題類別。
背景
我將從解釋需要解決方案的上下文開始。 如果您知道Plumbr性能監控的全部內容,則可以跳過此部分。 對于其他所有人,我們Plumbr都在構建性能監控解決方案。 我們的方法是獨特的,因為我們旨在使所有性能問題都具有源代碼的根本原因。
此類問題的最復雜類別之一是其根源隱藏在Java內存分配和管理中。 此類別中的問題包括:
- 內存不足;
- 面臨太頻繁/太長時間的GC暫停;
- 嘗試減少應用程序的內存占用。
我們對此類問題的解決方案是建立在對對象圖進行快照并從那里公開最耗費內存的數據結構的基礎上的。 結果,您將獲得運行時透明性,以了解JVM堆中實際發生的情況:
以上是我們在監視我們自己的服務時發現的示例。 如我們所見,在重大GC暫停后的某個時刻,我們占據了70%以上的舊一代。 老一代的高占用率通常會導致長時間的GC暫停,因此Plumbr捕獲了快照以顯示其中的實際內容。
在這種特殊情況下,我們發現包含ProbeDataProcessingTasks的處理隊列的大小已增長到近1 GB。 了解應歸咎于哪些數據結構使解決該問題變得微不足道。 結果,GC暫停的頻率和持續時間保持不變。
但是,拍攝這些快照有些昂貴。 捕獲快照所需的時間取決于堆中對象的數量以及它們之間的引用。 我們的代理商會仔細安排快照的時間,以避免自己成為性能瓶頸。
綜上所述:在我們的基礎架構中,此特殊功能導致不可預測的內存快照流入。 更糟糕的是,快照的大小也是不可預測的。 有時我們每小時可能只收到一個微小的快照,然后突然間,我們在很短的時間內被許多10 + G快照轟炸:
我們最初的解決方案存在問題
我們構建的第一個解決方案是專用的微服務,用于處理快照的傳入流。 我們立即開始面臨問題。 首先,我們還無法估算這些快照的大小。 最初配置的4G內存還遠遠不足以處理流向我們的較大快照。 要分析快照,我們需要將對象圖加載到內存中,因此快照越大,分析所需的RAM越多。
因此,我們需要從亞馬遜購買更大的計算機。 突然之間,微服務不再是微服務了。 正如我們很快發現的那樣,在您的每月賬單中實際上可以看到保持m4.10xlarge實例嗡嗡作響的24×7。 除了非常昂貴外,機器有99%的時間幾乎處于空閑狀態–發生的巨大堆快照很少見,因此經常會超額配置10倍以上的機器來處理偶發的峰值。
此外,分析持續時間很快就成為瓶頸。 快照需要花費10秒鐘到數十分鐘的時間來分析每個快照,因此當在短時間內到達多個大型快照時,隊列等待時間成為一個問題:
解決方案要求
了解了問題之后,下一步就是將問題簡化為解決方案的要求:
- 分析任務不應在隊列中等待數小時。 我們應該能夠并行處理它們。 每當一個巨大的快照到達并且需要很長時間進行分析時,其他快照就不應等待它完成。
- 對于每個快照,我們可以估計執行分析將需要多少堆。 我們希望使用盡可能多的資源,而不會過度配置基礎架構。
對于以前建立過彈性環境的人來說,解決方案的要求可能會很明顯。 對于那些還沒有的人,我將在下一部分中介紹解決方案體系結構和實現的關鍵案例。
建立解決方案
這些要求有效地指示我們,我們應該維護一個靈活的基礎架構,而不是一個單獨的專用實例。 實例應按需生成,實例類型應與接收到的快照的大小相對應。
因此,我們繼續將快照分析代碼包裝到docker容器中,并利用AWS ECS將此類容器用作集群中的任務。 這樣做之后,我們偶然發現了第一個問題:向外擴展并不像預期的那么瑣碎。
僅僅為每個分析生成一個適當大小的新實例并在之后立即終止的天真的方法被證明是一個壞主意。 啟動實例最多可能需要五分鐘,具體取決于實例類型。 此外,AWS每小時執行一次計費,因此,使一個實例運行60分鐘的成本要比運行十個實例每6分鐘的成本便宜十倍。
在這種情況下,典型的方法是使用AWS 自動擴展組。 顯然,這不適合我們,因為AWS無法根據ECS任務所需的內存量自動生成實例。 您無法將任務提交給ECS集群,除非該集群已經有足夠的資源來容納它。
我們的解決方案是根據分析任務所需的內存量將其劃分為多個存儲桶,并為每個存儲桶分配一個單獨的群集。 收到新快照后,我們檢查目標集群是否有足夠的可用資源來運行任務。 如果沒有,我們將在其自動擴展組中增加所需的實例數。 然后,AWS自動啟動一個具有適當大小的新實例。 因此,從本質上講,我們最終得到了六個存儲桶,每個存儲桶包含適當大小的實例,可以根據需求進行擴展:
第二個問題是通過擴展來解決自身問題。用于擴展的標準CloudWatch警報基于集群使用不足的情況。 如果集群閑置了足夠長的時間,我們會減少所需實例的數量。 “空閑”是根據群集中消耗的內存計算的,如果在45分鐘內內存使用率一直低于指定的閾值,則立即擴展并終止額外的實例。
這里也有一個警告:在自動伸縮組中進行伸縮時,AWS選擇一種特殊的方式來終止實例。 例如,如果一個群集有兩個實例,其中一個實例處于空閑狀態,而另一個實例正在運行分析,則完全有可能該活動實例將被殺死而不是空轉一個實例。
擴展問題的解決方案是,在分析期間,我們為執行此擴展的特定實例設置了擴展保護 。 當我們開始分析時,我們設置標志,并在完成時將其刪除。 自動縮放不會終止受保護而無法放大的實例。 最后一點就足夠了,從那以后我們就開始平穩運行。
找到了兩個問題的解決方案,我們得到了預期的結果。 更改后,隊列中等待的時間現在如下所示:
帶走
這是少數情況下的一種,您可以提高應用程序的性能,并減少容量需求以降低成本。 在大多數情況下,您必須為提高性能付出很大的代價,因此人們可以欣賞這些時刻。 現在,按需計算比以往任何時候都容易,因此也許您可以以類似的方式優化應用程序。
而且,如果除了彈性基礎架構的有趣案例之外,該帖子還引發了人們對如何獲得應用程序內存使用透明性的興趣,那就繼續免費試用Plumbr試用一下。
翻譯自: https://www.javacodegeeks.com/2016/05/elastic-infrastructure-practice.html
總結
以上是生活随笔為你收集整理的实践中的弹性基础架构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Lightroom:与 3D LUT C
- 下一篇: ActiveMQ 5.x中的消息持久性