如何避免AWS的高額賬單?
作者 | 劉龍飛
前言
Serverless架構(gòu)在今天已經(jīng)不再是新鮮的事物。該架構(gòu)具有多個特點:較低的運營和開發(fā)成本、能快速上線、自動擴展、安全性高和適合微服務(wù)等。各大云服務(wù)商也提供了各自的Severless解決方案。然而,盡管Serverless架構(gòu)在某些方面表現(xiàn)出色,但在當(dāng)前轟轟烈烈的“微服務(wù)”進程中,它仍然不是一種主要的選擇。
除了由于本身特性導(dǎo)致的使用場景受限外,我想乏善可陳的關(guān)于Serverless最佳實踐的總結(jié)也是一個重要的因素。我有幸參與了一項基于AWS搭建的Serverless (FaaS) 系統(tǒng)的開發(fā)工作,該系統(tǒng)提供了一組核心服務(wù)。
通過幾次系統(tǒng)故障調(diào)研和性能優(yōu)化的實際體驗,我發(fā)現(xiàn)系統(tǒng)監(jiān)控在Serverless架構(gòu)中至關(guān)重要。所以本文將從Serverless系統(tǒng)監(jiān)控的角度來展開一些討論。
哪些指標需要被監(jiān)控?
先分享一個真實發(fā)生的故事:
我們在對上文提到的FaaS 系統(tǒng)做一次部署時,由于API測試不通過導(dǎo)致流水線構(gòu)建失敗。調(diào)查發(fā)現(xiàn)是因為測試運行時間過久導(dǎo)致請求使用的令牌過期。這一發(fā)現(xiàn)直接指向了系統(tǒng)的性能問題。我們回溯大量流水線構(gòu)建記錄后發(fā)現(xiàn),API測試所耗時長在近一個月以來逐日遞增。
在調(diào)查了CloudWatch中各項觀測指標后發(fā)現(xiàn):從一個月前開始,Lambda的調(diào)用次數(shù)始終保持在最大并發(fā)量,并且Lambda一直處于高執(zhí)行時延狀態(tài)。最終找到根因在于一個會觸發(fā)Lambda執(zhí)行的消息事件由于某個bug被大量復(fù)制,并且該事件在被Lambda處理后原樣發(fā)回SQS,導(dǎo)致發(fā)生死循環(huán)。
盡管這個問題發(fā)生在非生產(chǎn)環(huán)境,但帶來的影響依然是非常大的:首先,測試環(huán)境性能明顯降低。另一方面,AWS是按使用收費。該問題導(dǎo)致一個月以來,Lambda,SQS,RDS,DynamoDB和CloudWatch等AWS服務(wù)被持續(xù)不斷地使用,因而產(chǎn)生了高額的賬單。
上述故事中反映出來的問題可能有很多方面,但缺乏監(jiān)控與告警無疑是導(dǎo)致該問題持續(xù)近一個月而沒有被發(fā)現(xiàn)和解決的罪魁禍首。那么,在Severless系統(tǒng)中,一般有哪些需要監(jiān)控的指標呢?其實AWS 的CloudWatch已經(jīng)給出了部分答案。不同于需要監(jiān)控CPU/內(nèi)存使用率等指標的長生命周期服務(wù),Severless服務(wù)的一大特點就是不需要開發(fā)和運維人員過多關(guān)注底層資源的分配和管理。那么與之相對應(yīng)地,針對Severless (FaaS) 而言,有以下一些值得關(guān)注的指標需要監(jiān)控并配置告警。
1. 執(zhí)行時延 (Duration)
一般Severless系統(tǒng)的函數(shù)都有最大執(zhí)行時間的限制。而且從系統(tǒng)的設(shè)計原則上講,一次函數(shù)調(diào)用也不應(yīng)執(zhí)行過長的時間。當(dāng)監(jiān)控到較多的長時延函數(shù)調(diào)用時,表明系統(tǒng)出現(xiàn)了異常情況,且極有可能導(dǎo)致性能問題。同時,長時延也意味著成本的增加。函數(shù)執(zhí)行時延的異常增高通常有如下原因:
- 如果該函數(shù)依賴于第三方服務(wù)或同一云平臺的其他服務(wù),則有可能是網(wǎng)絡(luò)通信,數(shù)據(jù)庫訪問等I/O操作延遲增大;
- 若該函數(shù)會批處理事件,則有可能是事件的生產(chǎn)者出現(xiàn)了異常,導(dǎo)致函數(shù)每次調(diào)用都需要處理大量任務(wù)。
所以函數(shù)執(zhí)行時延的異常增高,通常就是系統(tǒng)某一部分出現(xiàn)問題的信號。
2. 調(diào)用次數(shù) (Invocations)
調(diào)用次數(shù)表示某一時間范圍內(nèi)函數(shù)的調(diào)用次數(shù),它能夠反映當(dāng)前函數(shù)的活躍程度以及整體上的執(zhí)行情況。調(diào)用次數(shù)的突然變化也會反映系統(tǒng)中的異常情況。另外,監(jiān)控各個函數(shù)的調(diào)用情況也有助于我們合理配置該函數(shù)的最大并發(fā)量。
Severless系統(tǒng)的自動擴容就依賴于函數(shù)的調(diào)用情況。當(dāng)多個請求進入系統(tǒng),而當(dāng)前函數(shù)實例正在處理請求,系統(tǒng)會自動創(chuàng)建新的實例來處理其他請求。這個過程會一直持續(xù)到有足夠的函數(shù)實例來處理所有請求,除非達到最大并發(fā)量。一旦達到最大并發(fā)量后仍有待處理請求,則認為發(fā)生了瓶頸(Throttles)。出現(xiàn)瓶頸則是一個非常明顯的需要告警的情況,因此為瓶頸這一指標配置告警通常是非常有效的做法。
3. 錯誤率 (Error rate)
無論是函數(shù)調(diào)用錯誤或者是函數(shù)執(zhí)行異常都說明系統(tǒng)出現(xiàn)了非預(yù)期的行為,都需要盡快處理使系統(tǒng)恢復(fù)正常。但需要說明的是,如果系統(tǒng)出現(xiàn)的是性能問題,則不一定會導(dǎo)致錯誤率提高。所以不能僅依靠這單一指標來衡量系統(tǒng)的健康狀態(tài)。
以上是我認為的針對FaaS系統(tǒng)最基本的和最重要的三個指標。合理配置這幾個指標的監(jiān)控與告警,可以提前發(fā)現(xiàn)大多數(shù)非業(yè)務(wù)問題的系統(tǒng)異常,進而及時調(diào)查和解決問題避免更大的損失。
當(dāng)然,除了函數(shù),Severless系統(tǒng)還會依賴于大量云平臺提供的其他服務(wù)。以AWS為例,一個典型的Severless架構(gòu)通常會使用到API Gateway, SQS, SNS, DynamoDB和RDS等服務(wù)。而每個服務(wù)都有對應(yīng)的需要關(guān)心并監(jiān)控的指標,從學(xué)習(xí)了解的角度,有個技巧是直接去看CloudWatch提供了哪些已經(jīng)被自動監(jiān)控的指標,進而深入了解每個指標所代表的含義和所反映的深層次問題。了解得越清楚,在配置監(jiān)控和告警時會更得心應(yīng)手,收到告警后也有助于快速定位問題。
除了針對各個基礎(chǔ)服務(wù)的各類指標進行監(jiān)控外,監(jiān)控云平臺各個賬號的賬單也是避免損失的一大法寶。Severless系統(tǒng)中很多問題都會導(dǎo)致賬單的異常增加,而通常我們的精力都會放在系統(tǒng)問題的調(diào)查和修復(fù)上,后知后覺地才發(fā)現(xiàn)這一實打?qū)嵉慕?jīng)濟損失。大多云平臺都提供了成本管理功能。如AWS可以監(jiān)控賬單信息,并配置通知告警。甚至還可以配置預(yù)算操作,當(dāng)賬單達到某些條件時自動執(zhí)行一些預(yù)先定義好的行為,以達到止損的目的。
最后需要強調(diào)的是,除了監(jiān)控各項服務(wù)的基礎(chǔ)指標外,監(jiān)控業(yè)務(wù)指標以及由業(yè)務(wù)指標導(dǎo)向的技術(shù)指標也是監(jiān)控中非常重要的一環(huán),畢竟任何軟件系統(tǒng)提供具體業(yè)務(wù)都是第一位的。在這一方面,Severless架構(gòu)和其他類型架構(gòu)沒有太多本質(zhì)上的差別,所以不在此過多討論,但這也是設(shè)計系統(tǒng)監(jiān)控架構(gòu)時必不可少的。
分布式監(jiān)控
盡管云服務(wù)商已經(jīng)提供了很多基礎(chǔ)指標的監(jiān)控,但由于函數(shù)的事件驅(qū)動以及短生命周期特性,使我們很難從這些基礎(chǔ)指標中讀到一個完整的“故事”。若是我們想基于這些基礎(chǔ)監(jiān)控去分析系統(tǒng)性能瓶頸,或者嘗試調(diào)研特定業(yè)務(wù)問題,則會面臨重重困難。當(dāng)然,很容易想到的方式是分析日志來進行分析和調(diào)研,但以我們實際經(jīng)驗來看,嘗試從大量日志中發(fā)現(xiàn)性能瓶頸絕不是一個簡單的事情。
我們曾對上述FaaS系統(tǒng)嘗試進行整體性能調(diào)優(yōu),以及針對特定業(yè)務(wù)場景的性能優(yōu)化。需要做的事情大致分為以下步驟:識別性能瓶頸,對發(fā)現(xiàn)的瓶頸排列優(yōu)先級,依次嘗試優(yōu)化,本地驗證局部優(yōu)化效果,測試環(huán)境驗證特定業(yè)務(wù)場景下的優(yōu)化效果,生產(chǎn)環(huán)境驗證整體性能提升和特定業(yè)務(wù)場景優(yōu)化效果。在整個調(diào)查、修復(fù)和驗證過程中,遇到了很多痛點,其中最為明顯的就是尋找瓶頸和驗證優(yōu)化后效果兩個方面:
問題1:找到性能瓶頸
由于每個請求都會有若干個函數(shù)依次進行處理,其中整個過程還會包括消息隊列中事件的寫入和讀出,數(shù)據(jù)庫的連接和數(shù)據(jù)讀寫,第三方服務(wù)的訪問等過程。而我們所能采用的手段只能是首先分析日志進行初步定位,然后再本地調(diào)試進行更為精確地定位。因為現(xiàn)有日志缺少一些必要信息,所以需要增加日志。但這樣做,一方面帶來了額外的工作量,另一方面也會帶來大量的“噪音”,增加了分析日志的復(fù)雜程度。更重要的是,記錄大量日志有可能影響函數(shù)本身執(zhí)行的性能,也會增加監(jiān)控系統(tǒng)的成本。另外,本地調(diào)試也不是一件容易的事情。由于函數(shù)依賴于很多第三方服務(wù)或者云平臺其他服務(wù),本地需要隔離掉或提供虛擬的依賴。即使使用單元測試來觀察特定事件處理過程的執(zhí)行性能,因為要關(guān)注特定業(yè)務(wù)場景,也需要花費大量時間準備測試數(shù)據(jù)。
問題2:驗證優(yōu)化后效果
由于依賴過多,每次修復(fù)后都需要部署到個人測試環(huán)境中,而部署過程會花費較多的時間。另外,想要端到端地去驗證整體和局部性能的提升效果,也只能通過寫復(fù)雜的查詢命令來從日志中進行統(tǒng)計。在部署到生產(chǎn)環(huán)境后,想要統(tǒng)計特定業(yè)務(wù)場景下的性能提升也是很大的一個挑戰(zhàn)。由于日志主要關(guān)注局部過程,很難通過日志提取出特定業(yè)務(wù)場景并得到統(tǒng)計意義上的結(jié)果,所以遲遲無法衡量優(yōu)化后的真實效果。
雖然以上問題最終都通過各種手段得到了一定程度上的解決,但過程顯然不是輕松愉快的。以上問題的癥結(jié)在于單單依靠日志無法完整地貫通端到端過程,各處日志信息格式不統(tǒng)一,不能方便地聚合各個服務(wù)中的監(jiān)控信息。
分布式監(jiān)控系統(tǒng)就是可以有效解決這一類問題的技術(shù)手段。它通過采用統(tǒng)一數(shù)據(jù)模型和API,從各個系統(tǒng)子服務(wù)/函數(shù)中收集數(shù)據(jù),統(tǒng)一聚合和分析處理,以良好的可視化方式進行結(jié)果的呈現(xiàn)。構(gòu)建良好的分布式監(jiān)控系統(tǒng)可以從端到端的視角提供請求跟蹤,過程分析,甚至實時調(diào)試等功能。所以在業(yè)務(wù)場景較為復(fù)雜的情況下,為Serverless系統(tǒng)應(yīng)用分布式監(jiān)控工具應(yīng)該成為一種必然的選擇。
以AWS為例,它提供了原生的監(jiān)控工具X-Ray。X-Ray具備端到端跟蹤功能,可以監(jiān)控到Lambda,RDS,DynamoDB,SQS和SNS等服務(wù)中的元數(shù)據(jù),并提供應(yīng)用程序的端到端和跨服務(wù)視圖。Service map 則提供了應(yīng)用程序中的服務(wù)間匯總數(shù)據(jù)的連接視圖,其中包括平均延遲和故障率等。其他如延遲檢測,數(shù)據(jù)注釋和篩選等也是非常實用的功能。當(dāng)然,還有很多其他類似的工具也能達到相同的目的,我們在使用中根據(jù)具體需求進行選擇就好。
寫在最后
本文只是拋磚引玉,沒有過于深入的討論,目的是想總結(jié)與記錄在Serverless系統(tǒng)中試水的所見與所得。或許我們遇到的很多問題,有可能是因為Severless架構(gòu)目前并不適用于我們所面臨的復(fù)雜業(yè)務(wù)。但我想說,實踐是最好的老師,體驗和經(jīng)歷這些痛點才會讓人更有動力去思考和解決這些問題。監(jiān)控系統(tǒng)單拎出來也是一個龐大的話題,希望能通過本文讓我們更多地回過頭去思考監(jiān)控的目的,總結(jié)那些切實幫助和啟發(fā)到了我們的實踐。