神刀安全網

AWS 上的生產環境性能分析案例

本文是我在 gitchat 上的文章云計算生產環境架構性能調優和遷移套路總結(以 AWS 為例)的前半部分,本文對原文有所修改和總結。交流實錄請點擊這里

案例背景

案例是一個泰國網站的生產環境(請腦補一句“薩瓦迪卡”,為了敘述方便,下文中均以”薩瓦迪卡”指代這個網站。)“薩瓦迪卡”是一個 采用 WordPress + MySQL搭建的應用。這個遺留系統已經工作了五年。客戶已經把在其它 VPS 上平移到 AWS 上。平移(lift and shift)是說原樣復制,而遷移(migration)還要進行改造。而客戶唯一發揮 AWS 優勢的一點就是用了一個配置很高的 EC2 虛擬機 —— m4.4xlarge。這樣一臺配置的虛擬機有 16 個虛擬 CPU,64 GiB 的內存,以及 2000 Mbps 的網絡帶寬,最高 3000 IOPS 的 200GiB 的塊存儲設備(也就是硬盤)。

知識點: GiB 是用二進制計算的,GB 是用十進制計算的。1 GiB 是 2的30 次方,而1 GB 是10 的 9 次方,1 GiB 略大于 1GB。 而且,AWS 的 FreeTier 免費計劃是按 GB 計算的哦!

除了基本的網絡和虛擬機以外,“薩瓦迪卡” 的所有東西都放在一臺虛擬機上。沒錯,是所有東西——Web 服務器,反向代理,數據庫,上傳的文件——都放在一臺虛擬機上。唯一個一個負載均衡用來承載 HTTPS 證書,沒有使用集群,沒有高可用,沒有數據庫/應用分離,沒有防火墻,沒有 WAF,沒有 APM,沒有 CDN 而且,沒有持續交付流水線,所有部署都要 ssh 到機器上進行操作。如圖所示:

AWS 上的生產環境性能分析案例

原始架構

“薩瓦迪卡”的生產環境可以被認為是一個裸奔的肉雞。我曾經一度它已經被輪番入侵很久了,只是還沒有被發現而已。而且,“薩瓦迪卡”生產環境的唯一一臺服務器的內存率使用經常超過 95%,我很擔心它的狀況,任何一個小的 DoS,都不需要 DDoS,就可以讓它整站宕機了。

我于是把我的擔憂匯報給了客戶,客戶也意識到了問題。在我發現問題之前的一個月就啟動了“薩瓦迪卡”的翻新(Revamp)項目,讓這個應用保持原樣(Keep it as is),直到 6 個月后新項目上線,替換掉當前應用。

然而,沒想到我一語成讖。一天,“薩瓦迪卡”被刪庫了!

刪庫?別慌!

作為一個運維工程師,最悲催的事情就是“人在家中坐,鍋從天上來”。這天是世界杯的某一場小組賽,而我剛吃完晚飯正在洗碗。突然被客戶的 P1 告警(P1 – Priority 1,最高級別告警)驚嚇到,得知“薩瓦迪卡”被刪庫了。

判斷的依據是:

  1. “薩瓦迪卡”主頁打開是 WordPress 的初始化安裝頁面。證明應用是正常的,數據不在了。
  2. 在服務器上用 MySQL 客戶端登錄數據庫,找不到“薩瓦迪卡”的數據庫。

還好客戶每天有全量數據備份,于是客戶快速從全量備份恢復了數據庫,只是缺少了從備份點到故障點的業務數據。全量數據庫的備份文件有 10 GiB,這么大的表如果采用 mysqldump 會因為鎖表而導致 10 分鐘左右的停機時間(別問我怎么知道的)。

問題分析

在恢復應用的同時,我們也開始進行了分析的工作。首先,我們懷疑是被攻擊了。于是通過 AWS 的 CloudTrail(一種審計工具,用來記錄登錄 AWS 用戶的操作)和 主機上的命令歷史(history 命令)和登錄日志進行分析,結果一無所獲。其次,我開始檢查 MySQL 的日志(/var/lib/mysql/*.err),在日志上發現如下片段:

InnoDB: Log scan progressed past the checkpoint lsn 126908965949 180622 17:21:09  InnoDB: Database was not shut down normally! InnoDB: Starting crash recovery.  <此處省略很多行>  180622 17:21:32 InnoDB: Initializing buffer pool, size = 3.0G InnoDB: mmap(3296722944 bytes) failed; errno 12 180622 17:21:32 InnoDB: Completed initialization of buffer pool 180622 17:21:32 InnoDB: Fatal error: cannot allocate memory for the buffer pool 180622 17:21:32 [ERROR] Plugin 'InnoDB' init function returned error. 180622 17:21:32 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed. 

通過分析,我們發現 mysql 發現自己有問題的時候嘗試恢復數據庫,但因為虛擬機可用內存不足而加載存儲引擎失敗,導致找不到數據庫。因此,解決方案有以下三種:

  1. 采用工具進行對 mysql 服務器參數進行調優。
  2. 擴大內存,換個配置更高的虛擬機。
  3. 將應用和數據庫部署在不同的虛擬機實例或者 RDS (關系數據庫服務)上。

而三種有各自的問題:

對于方案1,數據庫調優需要頻繁重啟。對于生產環境來說,必須在低流量的時段(一般是夜間)進行。而且所花時間未知且效果很難保證。由于資源有上限,且進程相互影響,很難發現問題。所以風險較高,價值有限。

對于方案2,需要對虛擬機進行不停機鏡像復制,因此會導致部分數據丟失,而且數據同步恢復困難大。而且,不知道需要多少資源的虛擬才足夠。問題同方案1,只不過由于資源更多,下次出現同樣問題的時間更晚罷了。這個方案的風險雖然比第一種小,但用空間換時間的價值仍然有限,不曉得能撐到什么時候。而且,可能會帶來一定的資源浪費。

方案3是風險最小,價值最大的方案。它將數據作為核心資源并托管至高可用服務上,有效了隔離了風險,保護了數據的可用性。但唯一的缺點就是對于需要的資源和性能是未知的。因此,在實施這個方案之前,我們需要進行性能測量。

你可能會想,只需要增加一些基礎設施監控和 APM (Application Performance Monitoring,應用性能監控)就可以得到相應的數據了。然而,在生產環境的性能度量沒那么簡單。

首先,我們要保證生產環境的業務連續性。APM 也是一種應用程序,也會占用資源,你如何確定安裝和運行 APM 的過程不會造成生產環境停機?其次,如果一定會造成停機,那么會停機多久?當這些問題都是未知的情況下,魯莽的行為只能增加更多的不確定性風險。

因此,在遷移之前,我們要模擬生產環境進行度量并進行分析。

設計性能度量

性能度量是一個從“未知”到“已知”的過程。

首先,你需要明確所要度量的問題。你可以和你的小組一起商定需要解決的問題。在上面這個案例里,我們所需要回答的問題包括:

  1. 正常運行應用程序需要多少內存?
  2. 正常運行數據庫需要多少內存?
  3. 進行哪些操作會導致停機時間?停機時間會持續多久?
  4. 資源使用對性能的影響有多少?
  5. 性能拐點在哪里?

當然,對于 CPU,網絡和存儲,你也可以設計以上的問題。

然后,找到數據基線(Benchmark)

由于資源的使用是和用戶訪問數量息息相關的,你還需要知道資源使用的均值峰值邊際值

均值是資源使用基線,也就是最小值。

峰值是資源使用的警告線,如果過去發生過這么高。

邊際值是指每單位的用戶請求所消耗的資源。

一般來說,這些數據都可以從云計算提供商的非侵入式監控服務獲得,它的數據收集不會影響資源的性能。例如 AWS 的 CloudWatch 。我們可以根據過去 6 個月或者 3個月的時間來估計均值和峰值。但由于未來是不確定的,因此過去 6 個月或者 3 個?月的數據是建立在“未來訪問量不會突變”的假設基礎上的。例如,如果有類似于“6·18” 或者 “雙十一” 的流量高峰,則日常的數據參考意義不大。

如果缺乏這樣的手段,就要通過復制生產環境來度量了。

復制生產環境

復制生產環境的一點原則就是“盡量減少不同”,盡可能的按照生產環境的配置來構建你的沙盒環境以得到更接近真實的數據。很多云提供商都提供鏡像(Image)或者快照(Snapshot)的功能用來復制當前有狀態的資源。有時候二者是同一個意思。如果有區別,二者的區別在于以下幾點:

  1. 鏡像是全量,快照是增量。
  2. 鏡像的構建需要停機,而快照不需要。
  3. 鏡像生成時間長,快照生成時間短。
  4. 鏡像不能指定時間點部分還原,快照可以根據時間點部分還原。

無論是哪一種,我們都要選擇一個對生產環境影響最小的方案。在 AWS 中,我們可以根據當前的虛擬機實例構建虛擬機鏡像 AMI (Amazon Machine Images)。它提供兩種方式:一種是不重啟(no reboot),這種方式的缺點是會造成構建鏡像時間點以后的數據丟失。另外一種是在構建之前重啟實例,這樣不會導致數據丟失。

對于上述的案例來說,生產數據的完整性并不會影響我們的度量,因此,無需重啟實例。但如果你要度量重啟實例會帶來多少數據丟失,則需要重啟實例。

此外,為了保證你不會誤操作,我建議你在非生產環境的云計算賬號下重建應用。如果你一定要在同一個賬戶中進行復制,請確保你做好了生產環境資源隔離。

設計測試場景

當你在測試環境下復制了生產環境,你就有了一個安全的沙箱來進行測試了。當我們開始進行性能測試的時候,我們要通過“整體”的測試來計算對“局部”的影響。并找到。以“薩瓦迪卡”為例,我們通過 AWS 上的數據得到了“薩瓦迪卡”生產環境的平均響應時間:0.2 ~ 0.4 秒,RPM(Requests Per Minute 每分鐘請求)大概在 4500 左右。

因此我們設計了如下測試場景:

  1. 空閑使用率:0 請求的時候,資源使用率。
  2. 1 個,10 個,20 個 并發請求的時候,資源使用率和響應時間,用于計算邊際資源使用率。
  3. RPM 和生產環境 RPM 均值相等的情況下,資源使用率和響應時間。
  4. 2 倍 ,4 倍, 10 倍 生產環境 RPM 均值的情況下,資源使用率和響應時間。
  5. 模擬生產環境的 RPM 增長速度(逐步增加請求到相應值,例如 5 分鐘增長到 2000 RPM)進行測試。
  6. 模擬生產環境極限 RPM 增長速度(一次增加請求到對應值,例如 5 秒鐘增長到 2000 RPM)進行測試。

根據以上的測試場景,我們可以構建資源使用率和響應時間之間的關系。

如果你有 CDN 或者 URL 訪問分析數據,可以它來構建你的測試案例。如果什么沒有,例如“薩瓦迪卡”這種情況,你就可以使用主頁的 URL 來進行測試。常用的工具有 Selenium, Jmeter 和 Gatling。你可以用 Selenium 錄制一個用戶訪問的腳本,來模擬用戶訪問。你也可以通過 Jmeter 或 Gatling 來增加并發進行負載測試,后者能提供更加有用的信息。

如果你無法模擬足夠多的真實用戶數據,把以上的工具生成的腳本或配置放到 flood.io 上運行,得到更好的參考報告,如下圖所示:

AWS 上的生產環境性能分析案例

flood.io

如果你需要度量某些操作的停機時間,你可以在進行負載測試的時候進行操作。也可以使用我寫的小工具 wade (Web Application Downtime Estimation)來測試。關于 wade 的故事可以參考 一怒之下,我寫了一個開源流量測試工具

通過模擬“薩瓦迪卡”的訪問數據,我得到了以下數據:

  1. 當 Web 服務器(Apache)重啟完,僅有健康檢查訪問的情況下,系統占用 367 MiB 內存。
  2. 數據庫占用 10 GiB 左右內存,也就是說,給 Web 應用剩下的內存有 53 GiB 左右。
  3. 分別度量了 1個用戶,10 個用戶,20 個用戶并發訪問下的內存使用情況。平均每處理一個請求,最多需要消耗 133 MiB 內存。
  4. 也就是說,剩下的內存最大能服務 400 個左右的用戶的并發訪問。如果超過 400 個用戶,系統會因為資源不足而宕機。
  5. 升級虛擬機 Linux 中的軟件包和安全補丁會帶來 5 秒鐘左右的停機。
  6. APM (NewRelic)的安裝會占用 63 MiB 左右內存且無停機時間。

編寫性能度量報告

當我們完成了性能度量的時候,就要編寫一份性能度量報告。性能度量報告包含以下 6 個部分:

  1. 背景:主要回答為什么(Why)要做這一次性能度量。
  2. 關鍵問題:通過性能度量期望知道哪些問題(What)。
  3. 測試設計:主要介紹度量方法(How),以及度量方法中的注意事項。
  4. 測試條件:由于是模擬測試,要強調與真實值的匹配情況,哪些部分重要,哪些部分不重要。
  5. 測試數據結果:采用工具得出的真實數據,要有源可查,最好是截圖。
  6. 結論:根據數據的計算解答第 2 步 提出的關鍵問題。
  7. 建議:根據度量數據得出的下一步優化建議。

至此,我們完成了對生產環境性能的分析。接下來,就要為性能設計架構遷移方案了。請關注下篇《AWS 上的生產環境架構優化案例

轉載本站任何文章請注明:轉載至神刀安全網,謝謝神刀安全網 » AWS 上的生產環境性能分析案例

分享到:更多 ()
河北11选5开奖查询