HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

AWS Lambda 收集自定义指标 (Metrics) 最佳实践

  • 2019-10-04
  • 本文字数:5056 字

    阅读完需:约 17 分钟

AWS Lambda 收集自定义指标 (Metrics) 最佳实践

前言

AWS Lambda 是非常受欢迎的无服务器运行代码的云服务。我们知道 AWS Lambda 运行所产生的日志(logs)会自动收集到 CloudWatch Logs 中,Lambda 所产生的通用运行指标(metrics) 例如:“调用数”、“持续时间”、“错误”、“并发数”等都会自动收集到 CloudWatch Metrics 中监控。而本文将阐述几种自定义指标的收集方法及其优缺点。


有一些场景是需要收集 AWS Lambda 运行产生的一些数据指标的,例如:用户访问行为相关的数据,某个函数分段的执行时长,某个实时参数等。这些指标与 Lambda 的运行本身无关,所以不像 Lambda“调用数”、“持续时间”这些通用指标会自动反映到 CloudWatch 上。如果是有服务器(例如 Amazon EC2)的常见做法,可以记录到本地文件中,由一个独立 Agent 定时发送到 CloudWatch 上,例如在 EC2 上安装 CloudWatch Agent 去做收集。参见“使用 CloudWatch 代理从 Amazon EC2 实例和本地服务器收集指标和日志”。


而无服务器的 Lambda 虽然有一个本地临时目录(\tmp)可以写入文件,但 Lambda 运行环境是会被暂停或回收的,写本地文件并不可靠,可能会导致数据来不及发送就暂停或丢失了,那这些自定义的 Lambda 运行指标要怎么收集和监控呢?

预备知识

  1. AWS Lambda 已与 CloudWatch Logs 集成,函数所产生的日志会自动收集到 CloudWatch Logs 。输出和查看日志的方法参见 AWS Lambda 文档。不同的开发语言有相应的输出语句,例如以下 Python 语句都能生成日志:


  • print 语句

  • logging 模块中的 Logger 函数(例如,Logger.info 和 logging.Logger.error)

  • 其他语言例如 Node.js 的 console.log(),Java 的 Log4j 2 或 LambdaLogger.log(),Golang 的 log.Print() 都有类似的效果,自动输出日志到 CloudWatch Logs。


  1. 如果是做故障定位和性能优化的,可以采用 AWS X-Ray 方便地跟踪 Lambda 函数运行

  2. 如果你发现需要对 Lambda 函数代码分段运行时间进行很多监控,并进行优化,则建议先重新考虑一下,是否你的 Lambda 函数设计得太大了。单个 Lambda 函数是否包含了过多的业务逻辑?如果是有多个步骤组成的,可以考虑改为多个 Lambda 函数,并使用 AWS Step Function 工作流进行协同。

Lambda 自定义指标的收集和监控

以下列举三种收集 Lambda 自定义指标的方法,分别是


  • 直接发送 CloudWatch PutMetricData API 接口收集

  • 利用 CloudWatch 日志过滤收集

  • 利用 CloudWatch 日志触发 Lambda 来处理和提交 CloudWatch 接口

  • 方法一:直接调用 CloudWatch PutMetricData API

  • CloudWatch 提供了 PutMetricData API,可以在函数代码中直接调用该 API 把指标数据提交到 CloudWatch。



优点:Lambda 函数运行的时候同步请求发送数据,指标最小粒度达到 1 秒。


缺点:同步方式,增加了函数的运行时间。您将在后面的实验结果中看到,例子中每次发送 PutMetricData 的时间约 50ms。时延依赖于 CloudWatch API 的响应速度,如果 CloudWatch API 有异常则直接对主业务逻辑造成影响。


另外要注意,默认的软限制是 PutMetricData 150 transactions per second (TPS),可申请提升。


实现方式,例如以下 Python 编写的 Lambda 示例:


import boto3
CWclient = boto3.client('cloudwatch')

def lambda_handler(event, context):
CWclient.put_metric_data(
Namespace='LambdaCustomMetrics',
MetricData=[
{
'MetricName': 'myPutCustomMetric',
'Value': value,
'StorageResolution': 1
},
]
)
return
复制代码


注意:Lambda 的运行角色需要有 cloudwatch:PutMetricData 执行权限


方法二:通过 CloudWatch Logs Filter 传递指标


如前所述,Lambda 已经集成了 CloudWatch Logs,可以在函数中把需要传递的指标写入日志,并在 CloudWatch Logs 中设置过滤器(Filter)来提取指标。



优点:异步方式,避免了对函数运行时间的影响。 Lambda 写 Log 是后台自动完成无需考虑架构。


缺点:统计结果只精确到分钟。且需要配置管理 Logs Filter 。CloudWatch Logs Filter 每个日志组只能设置 100 个,硬限制,不适合一个 Lambda 有大量个性化指标和粒度为秒的情况。


实现方式,例如以下 Lambda 的 Python 语句将写入日志:


print(‘my_metric_in_log myCustomMetric’, str(value))


然后,在 CloudWatch Logs 控制面板对应 Lambda 的日志组(Log Group)中设置 Filter



设置过滤模版(Filter Pattern),本例中写入的日志是“my_metric_in_log 名字 数值”,所以模版配置成“[p=my_metric_in_log, name, value]”。您可以点击”Test Pattern”测试现有日志的匹配结果。



匹配到关键字 my_metric_in_log 的日志,就会取出值到 value 变量。在下一步中,配置 Metric 值为 $value 变量即可实现从日志中提取指标。考虑到避免空数据的情况,可选设置默认值为 0。



保存了 Filter 的配置后,可以点击您设置的指标名称跳转到对应的监控指标界面。或者点击 Create Alarm 配置告警阀值,并实现联动,例如发送 SNS 通知或者触发 Lambda 做自动化处理。



方法一、二的示例和实验结果对比


我们用一个 Lambda 函数同时做方法一和方法二,我们来对比一下。代码示例如下:


本例中,我们随机生成一个 value 作为要发送的指标数据,每个数据是随机的 1-20 整数。每次发送指标到 CloudWatch PutMetricData API 接口的间隔为 1 秒,并同时写入日志。让 Lambda 运行 600 秒,即我们应该收到 600 次发送指标数据。最后返回统计平均每次 PutMetricData 的时间。


import boto3
import time
import datetime
import random
CWclient = boto3.client('cloudwatch')

def lambda_handler(event, context):
total_detal = 0
for i in range(0, 600):
# caculate put metric time
start = datetime.datetime.now()

# put custom metric
value = random.randint(1, 20)
CWclient.put_metric_data(
Namespace='LambdaCustomMetrics',
MetricData=[
{
'MetricName': 'myPutCustomMetric',
'Value': value,
'StorageResolution': 1
},
]
)
end = datetime.datetime.now()
delta = ((end - start).microseconds) / 1000
total_detal += delta
time.sleep(0.95)
print('my_metric_in_log myCustomMetric', str(value))
return 'avg_detal: '+str(total_detal/600)

复制代码


当我们用 CloudWatch 同时打开 PutMetricData 获得的指标(下图左侧单位,蓝色曲线)和通过 Log Filter 获得的指标(下图右侧单位,橙色曲线)。


  • 统计周期一分钟

  • 选择统计方式为“求和” (Sum),统计周期为 1 分钟。我们会看到两种方式的曲线非常重合,时延和数值的差异并不大,结果如下图:


把统计方式改为“采样数量” (Sample Count),统计周期依然是 1 分钟。两种方式也是一致的,每分钟都收到了 60 次数据。



统计方式改为“平均值” (Average),两种方式结果相近。



  • 统计周期 1 秒

  • 如果把统计周期改为 1 秒,我们再看“求和” Sum、“采样数量” Sample Count 和“平均值” Average 的结果。采用 PutMetricData 收集的数据可以达到秒级的粒度,而采用 Logs Filter 的方式则不能。




我们再看看 PutMetricData 所消耗的时间,在本次测试的这 10 分钟内,每次请求的平均时间接近 50ms。



方法三:CloudWatch Logs 触发 Lambda 做指标提取并提交


即把方法一中的主 Lambda 函数中的 PutMetricData 操作剥离成一个独立的提取指标的 Lambda,主 Lambda 像方法二那样把指标写入 Logs ,然后配置 CloudWatch Logs 触发提取指标的 Lambda 从 Logs 中提取并提交 CloudWatch 指标收集



优点:主函数逻辑和提交指标异步解耦,互相不影响。CloudWatch Logs 触发 Lambda 是异步触发,出错会自动重试 2 次。统计精度达到秒级。不受每个 Logs Group 的 Filter 100 个数量的限制,完全自定义,非常灵活。


缺点:架构变复杂了。 Lambda 的并发多了一倍。


实现方式,新建一个从 Logs 中提取指标的 Lambda,配置这个 Lambda 由 CloudWatch Logs 触发,选择主 Lambda 函数的日志组,配置筛选模式(Filter Pattern)跟前面方式二在 CloudWatch Logs 中配置 Filter Pattern 一样的方式。如下图:



编写处理日志的 Lambda 函数。注意 CloudWatch Logs 触发 Lambda 所提交的 event 是经 base64 编码且是压缩的,需解压处理,示例代码如下:


import json
import gzip
import base64
import boto3
CWclient = boto3.client('cloudwatch')

def lambda_handler(event, context):
# TODO implement
payload = gzip.decompress(base64.b64decode(event['awslogs']['data']))
value_list = json.loads(payload)['logEvents']
for i in value_list:
try:
value = int(i['extractedFields']['value'])

# put custom metric
CWclient.put_metric_data(
Namespace='LambdaCustomMetrics',
MetricData=[
{
'MetricName': 'SecondLambdaPutMetric',
'Value': value,
'StorageResolution': 1
},
]
)
except Exception as e:
print(e)
return

复制代码


匹配了 Filter Pattern 所输出的 logEvnets 示例如下:


{
"messageType": "DATA_MESSAGE",
"owner": "31340000000",
"logGroup": "/aws/lambda/putLogsMetrics",
"logStream": "2019/03/29/[$LATEST]a4e25d49479441439bf06f41dfeb339c",
"subscriptionFilters": [
"Lambda_custom_metric_proccess_filter"
],
"logEvents": [
{
"id": "34651910332582237088994078865747388003785804733060153344",
"timestamp": 1553845399519,
"message": "my_metric_in_log myCustomMetric 15\\n",
"extractedFields": {
"p": "my_metric_in_log",
"name": "myCustomMetric",
"value": "15"
}
}
]
}
复制代码


留意这里有个“extractedFields”属性,就是填了筛选模式(Filter Pattern)后系统从 message 中匹配出来的,如果不填 Pattern,则没有“extractedFields”属性,只有前面那个“message”属性。


然后提交 PutMetricData 到 CloudWatch 操作同方法一,此处不再赘述。


由于本例的 Lambda 是每秒发一次数据,所以我们这里用统计的每秒“平均值”展示结果:


左边单位蓝色曲线的是主 Lambda 函数直接 PutMetricData,右边单位橙色曲线的是经过 Log 触发后的 Lambda PutMetricData。数据基本一致,曲线显示延迟了 2 秒左右。



方法三延伸 1:


当然,如果有多个 Lambda 应用,可以共用一个专门的转发指标的 Lambda 。如下图:



方法三延伸 2:


要注意,默认的软限制是 PutMetricData 150 transactions per second (TPS),可申请提升。如果并发较高的,建议用 Kinesis 收集汇聚,然后再发送 CloudWatch Metric 或发送其他指标监控平台。



相关文章:


使用 CloudWatch 代理从 Amazon EC2 实例和本地服务器收集指标和日志


https://docs.aws.amazon.com/zh_cn/AmazonCloudWatch/latest/monitoring/Install-CloudWatch-Agent.html


AWS Lambda 文档 https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/welcome.html


Amazon CloudWatch 发布自定义指标” 文档”


https://docs.aws.amazon.com/zh_cn/AmazonCloudWatch/latest/monitoring/publishingMetrics.html


AWS Python SDK 文档


https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cloudwatch.html#CloudWatch.Client.put_metric_data


AWS X-Ray 文档


https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/lambda-x-ray.html


作者介绍:


黄卓斌


AWS 解决方案架构师,拥有 20 年移动互联网、大型企业复杂应用系统架构和设计经验。擅长分布式和高可用软件系统设计,微服务与无服务器架构设计,移动互联网应用和大数据分析解决方案。加入亚马逊前,曾任职移动互联网公司 CTO,还曾任职华为、诺基亚等,以及长期驻访美国、印度等从事合作项目开发。


本文转载自 AWS 技术博客。


原文链接:


https://amazonaws-china.com/cn/blogs/china/aws-lambda-collect-new-metrics-best-cases/


2019-10-04 20:251209
用户头像

发布了 1848 篇内容, 共 113.9 次阅读, 收获喜欢 78 次。

关注

评论

发布
暂无评论
发现更多内容

快递鸟预约取件API接口代码流程

快递鸟

快递

重新理解RocketMQ Commit Log存储协议

百度搜索:蓝易云

CompletableFuture总结和实践

百度搜索:蓝易云

MySQL数据迁移到SQLServer数据库

RestCloud

MySQL 数据库 数据传输 ETL SqlServer

cleanmymac有必要买吗?Mac清理软件哪个好用?

阿拉灯神丁

软件包 清理工具 mac系统维护 CleanMyMac X中文版

GO语言常用标准库fmt

百度搜索:蓝易云

Openharmony的启动流程

百度搜索:蓝易云

国内首位聋人 Android 软件工程师体验通义灵码,“这真是太棒了”

阿里巴巴云原生

阿里云 云原生 通义灵码

企业数字化转型对IT治理模式的影响研究

快乐非自愿限量之名

人工智能 大数据 运维

Hume.ai 升级:自研情感模型集成 Claude 和 Fal;数字嗅觉公司 Osmo 用 AI 实现气味「传送」

声网

项目管理流程图解:简化复杂任务

爱吃小舅的鱼

项目管理 项目流程 项目规划

鸿蒙 next 实现应用内的暗黑模式切换

flfljh

鸿蒙

恭喜!龙蜥赛项25支队伍获得首届中国研究生操作系统开源创新大赛一二三等奖

OpenAnolis小助手

开源 操作系统 龙蜥社区 龙蜥赛事

共建行业生态,智谱大模型生态合作伙伴联盟成立

技术研究院

UBBF 2024,建起超宽带与AI间的博斯普鲁斯大桥

脑极体

ppt目录页怎么做好看?一键切换ppt模板布局的神器来了!

职场工具箱

效率工具 职场 PPT 高效办公 AI生成PPT

认识鸿蒙Context

龙儿筝

鸿蒙

Flutter OS外接纹理适配简介

flfljh

鸿蒙

并发编程之同步/异步/回调/任务 工作流程分析图解

肖哥弹架构

Java 并发编程 高并发

腾讯云的相关DDoS计费问题概览

网络安全服务

DDoS 带宽 API 接口 腾讯云服务器 DDoS 攻击

NocoBase 实战教程 —— 任务管理系统

NocoBase

开源 低代码 教程 无代码

基于 EventBridge + DashVector 打造 RAG 全链路动态语义检索能力

阿里巴巴云原生

阿里云 云原生 EventBridge

【论文速读】| PathSeeker:使用基于强化学习的越狱攻击方法探索大语言模型的安全漏洞

云起无垠

如何在IT项目管理中实现团队协作

爱吃小舅的鱼

项目管理 IT IT项目管理

国内首位聋人 Android 软件工程师体验通义灵码,“这真是太棒了”

阿里云云效

阿里云 云原生 通义灵码

Flutter与鸿蒙三方库ohos的适配

flfljh

鸿蒙

SVN和GIT命令对比

百度搜索:蓝易云

Flutter+鸿蒙NEXT开发获取系统文件路径

flfljh

鸿蒙

“AI”就一起来!开放原子联合龙蜥推出 OS Copilot 学习赛,show 出你的创意

OpenAnolis小助手

Linux AI 操作系统 OS Copilot

龙蜥副理事长张东:加速推进 AI+OS 深度融合,打造最 AI 的服务器操作系统

OpenAnolis小助手

开源 AI 操作系统 龙蜥操作系统大会

研发管理与项目管理:痛点分析与建议

爱吃小舅的鱼

项目管理 研发管理 管理项目

AWS Lambda 收集自定义指标 (Metrics) 最佳实践_语言 & 开发_亚马逊云科技 (Amazon Web Services)_InfoQ精选文章