之前寫過一篇文章:Serverless架構(gòu)與資源評估:性能與成本探索?
是關(guān)于性能和成本的探索著隆,探索之后攻晒,就不得不引出一個新的問題:我們在使用Serverless架構(gòu)的時候匈睁,要如何來設(shè)置自己的運行內(nèi)存和超時時間呢?
其實評估的方法有很多,但是今天我想分享一下我的評估方法色鸳。
首先,我會將我的函數(shù)上線见转,選擇一個稍微大一點的內(nèi)存命雀,例如,我將我的函數(shù)執(zhí)行一次:
得到這樣的結(jié)果斩箫,我就將我的函數(shù)設(shè)置為128M或者256M吏砂,超時時間設(shè)置成3S。
然后我讓我的函數(shù)跑一段時間乘客,例如我這個接口每天觸發(fā)次數(shù)大約為4000+次:
我就將這個函數(shù)的日志撈出來赊抖,寫成一腳本,做統(tǒng)計:
import json, time, numpy, base64
import matplotlib.pyplot as plt
from matplotlib import font_manager
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.scf.v20180416 import scf_client, models
secretId = ""
secretKey = ""
region = "ap-guangzhou"
namespace = "default"
functionName = "course"
font = font_manager.FontProperties(fname="./fdbsjw.ttf")
try:
cred = credential.Credential(secretId, secretKey)
httpProfile = HttpProfile()
httpProfile.endpoint = "scf.tencentcloudapi.com"
clientProfile = ClientProfile()
clientProfile.httpProfile = httpProfile
client = scf_client.ScfClient(cred, region, clientProfile)
req = models.GetFunctionLogsRequest()
strTimeNow = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(time.time())))
strTimeLast = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(time.time()) - 86400))
params = {
"FunctionName": functionName,
"Limit": 500,
"StartTime": strTimeLast,
"EndTime": strTimeNow,
"Namespace": namespace
}
req.from_json_string(json.dumps(params))
resp = client.GetFunctionLogs(req)
durationList = []
memUsageList = []
for eveItem in json.loads(resp.to_json_string())["Data"]:
durationList.append(eveItem['Duration'])
memUsageList.append(eveItem['MemUsage'] / 1024 / 1024)
durationDict = {
"min": min(durationList), # 運行最小時間
"max": max(durationList), # 運行最大時間
"mean": numpy.mean(durationList) # 運行平均時間
}
memUsageDict = {
"min": min(memUsageList), # 內(nèi)存最小使用
"max": max(memUsageList), # 內(nèi)存最大使用
"mean": numpy.mean(memUsageList) # 內(nèi)存平均使用
}
plt.figure(figsize=(10, 15))
plt.subplot(4, 1, 1)
plt.title('運行次數(shù)與運行時間圖', fontproperties=font)
x_data = range(0, len(durationList))
plt.plot(x_data, durationList)
plt.subplot(4, 1, 2)
plt.title('運行時間直方分布圖', fontproperties=font)
plt.hist(durationList, bins=20)
plt.subplot(4, 1, 3)
plt.title('運行次數(shù)與內(nèi)存使用圖', fontproperties=font)
x_data = range(0, len(memUsageList))
plt.plot(x_data, memUsageList)
plt.subplot(4, 1, 4)
plt.title('內(nèi)存使用直方分布圖', fontproperties=font)
plt.hist(memUsageList, bins=20)
with open("/tmp/result.png", "rb") as f:
base64_data = base64.b64encode(f.read())
print("-" * 10 + "運行時間相關(guān)數(shù)據(jù)" + "-" * 10)
print("運行最小時間:\t", durationDict["min"], "ms")
print("運行最大時間:\t", durationDict["max"], "ms")
print("運行平均時間:\t", durationDict["mean"], "ms")
print("\n")
print("-" * 10 + "內(nèi)存使用相關(guān)數(shù)據(jù)" + "-" * 10)
print("內(nèi)存最小使用:\t", memUsageDict["min"], "MB")
print("內(nèi)存最大使用:\t", memUsageDict["max"], "MB")
print("內(nèi)存平均使用:\t", memUsageDict["mean"], "MB")
print("\n")
plt.show(dpi=200)
except TencentCloudSDKException as err:
print(err)
運行結(jié)果:
----------運行時間相關(guān)數(shù)據(jù)----------
運行最小時間: 6.02 ms
運行最大時間: 211.22 ms
運行平均時間: 54.79572 ms
----------內(nèi)存使用相關(guān)數(shù)據(jù)----------
內(nèi)存最小使用: 17.94921875 MB
內(nèi)存最大使用: 37.21875190734863 MB
內(nèi)存平均使用: 24.83201559448242 MB
通過這樣一個結(jié)果寨典,可以清楚看出氛雪,近500次,每次函數(shù)的時間消耗和內(nèi)存使用耸成。
可以看到時間消耗报亩,基本在1S以下,所以此處超時時間設(shè)置成1S基本就是合理的井氢,而內(nèi)存使用基本是64M以下弦追,所以此時內(nèi)存設(shè)置成64M就可以。
我還有另一個函數(shù):
----------運行時間相關(guān)數(shù)據(jù)----------
運行最小時間: 63445.13 ms
運行最大時間: 442629.12 ms
運行平均時間: 91032.31301886792 ms
----------內(nèi)存使用相關(guān)數(shù)據(jù)----------
內(nèi)存最小使用: 26.875 MB
內(nèi)存最大使用: 58.69140625 MB
內(nèi)存平均使用: 36.270415755937684 MB
如果上一個函數(shù)花竞,是一個非常平穩(wěn)和光滑的函數(shù)劲件,很容易預(yù)估資源使用率,那么這個函數(shù)則可以很明顯看出波動约急,運行時間層面零远,可以看到絕大部分在150S以下,部分不到200S厌蔽,最高峰值近450S牵辣,所以這個時候,我們就可以根據(jù)我們的業(yè)務(wù)需求來判定奴饮,這個突然之間增加到450S的請求纬向,是否可以被中止,此時戴卜,我推薦將這個函數(shù)的超時時間設(shè)置為200S逾条,至于內(nèi)存部分,可以看到絕大部分都是40MB以內(nèi)投剥,部分出現(xiàn)在45-55MB师脂,最高未超過60MB,所以此時可以推薦這個函數(shù)設(shè)置為64MB。
其實目前來說危彩,云函數(shù)在執(zhí)行時攒磨,可能會有一定的波動泳桦,所以無論是內(nèi)存使用還是超時時間汤徽,都可能會出現(xiàn)一定的波動,可以根據(jù)自身的業(yè)務(wù)需求來做一些舍棄灸撰,將我們的資源使用量壓到最低谒府,節(jié)約成本。
我的做法基本就是分為兩步走:
- 簡單運行兩次浮毯,評估一下基礎(chǔ)資源使用量完疫,然后設(shè)置一個稍微偏高的值;
- 函數(shù)運行一段時間债蓝,得到一定的樣本值壳鹤,在進行數(shù)據(jù)可視化和基本的數(shù)據(jù)分析,得到一個相對穩(wěn)定權(quán)威的數(shù)據(jù)饰迹;