每 5 秒调用一次 Lambda 函数
Posted
技术标签:
【中文标题】每 5 秒调用一次 Lambda 函数【英文标题】:Invoking a Lambda function every 5 seconds 【发布时间】:2018-05-17 17:50:33 【问题描述】:我的问题
出于某些监控目的,我想每 5 秒调用一次 AWS Lambda 函数。
根据the docs,
不支持少于一分钟的速率频率。
我尝试了什么
STFW。
我的问题
我可以每 5 秒自动调用一次 AWS Lambda 函数吗?
【问题讨论】:
抱歉,STFW 代表什么? 搜索 fine 网络。正如您想象的那样,类似的首字母缩写词也很流行 【参考方案1】:虽然我不能推荐这种方式,但是如果你真的需要每 5 秒执行一次 Lambda 函数,你可以试试这个:
-
创建一个每分钟执行一次的 Lambda 函数 A。
创建一个由 Lambda 函数 A 每 5 秒触发一次的 Lambda 函数 B。(A 触发 B,等待 5 秒,触发 B,等待 5 秒,...)
大约一分钟后停止 Lambda 函数 A。 (您可以阅读remaining miliseconds from the context object => 如果达到>55 秒,则停止执行)
如果你真的需要这个,请慎重考虑。
【讨论】:
只使用步进函数。 aws.amazon.com/blogs/architecture/…【参考方案2】:您可以为此使用阶跃函数和 lambda - 查看 https://aws.amazon.com/blogs/architecture/a-serverless-solution-for-invoking-aws-lambda-at-a-sub-minute-frequency/
【讨论】:
这应该是现在的正确答案(尽管其他人提到的成本影响仍然相关) 需要注意的是,step 函数会在其执行历史日志中有 25k 个条目后自动停止(失败状态)。对于具有许多状态的阶跃函数,这可能会很快发生。 docs.aws.amazon.com/step-functions/latest/dg/…【参考方案3】:我想我还是会回答这个问题。
您的整个问题是,无服务器不太适合几乎恒定的工作负载。它们更适合快速缩小和缩小。但是,如果这不是您的用例,那么您几乎可以肯定使用 ec2 实例在成本方面会更好,您甚至可以保留一个。但我确实知道您失去了 Lambda 的高可用性和其他一些好处,这可能希望您仍然采用这种方法。
如果您想使用大锤来实现这种方法,您可以使用 StepFunction。 StepFunction 可以以秒为单位等待,但唯一的问题是它们不会无限期运行并且会在 1 年后死亡,因此您的 StepFunction 需要在它死亡之前启动另一个 StepFunction,或者您将不得不通过其他一些机制,即云手表闹钟。
这种方法对于你所说的调用次数也需要一点钱,会花费超过
(31,540,000 [秒/年] / 5 [秒/调用] x $0.000025 = $157.7)
加上您的 Lambda 成本,(我认为您实际上需要 2 次状态转换,所以我认为您将这个数字加倍)
如果你只打算跑 1 可能没问题。但是如果说跑 100 会远远超过 10k!毫无疑问,一个 ec2 实例的成本会更低。
【讨论】:
“你的全部问题是无服务器不适合几乎恒定的工作负载。”我不认为这是真的,我们将 lambda 用于许多恒定的工作负载(例如流式传输/转换日志事件)。 这很好,但对于这种类型的工作负载,它并不是最具成本效益的架构。【参考方案4】:以下是无服务器的全部内容,每秒钟执行一次步进函数 - 永远和一天:
service:
name: your-service
plugins:
- serverless-python-requirements
- serverless-step-functions
- serverless-pseudo-parameters
custom:
pythonRequirements:
dockerizePip: non-linux
region: eu-west-1
stage: dev
package:
exclude:
- node_modues/**
- venv/**
provider:
name: aws
iamManagedPolicies:
- arn:aws:iam::aws:policy/AWSStepFunctionsFullAccess
- arn:aws:iam::aws:policy/AWSLambdaFullAccess
runtime: python3.7
versionFunctions: false
region: $self:custom.region
stage: $self:custom.stage
environment:
PUSH_FUNCTION: arn:aws:lambda:#AWS::Region:#AWS::AccountId:function:$self:service-$self:custom.stage-push
functions:
schedulerStart:
handler: scheduler.start
events:
- schedule: rate(1 minute)
environment:
STATEMACHINE_ARN: $self:resources.Outputs.SchedulerStateMachine.Value
scheduler:
handler: scheduler.handle
push:
handler: scheduler.push
stepFunctions:
stateMachines:
everySecond:
name: SchedulerStateMachine
definition:
Comment: "Step Function invoked every minute"
StartAt: ConfigureCount
States:
ConfigureCount:
Type: Pass
Result:
index: 0
count: 60
ResultPath: "$.iterator"
Next: "Iterator"
Iterator:
Type: Task
Resource: "arn:aws:lambda:#AWS::Region:#AWS::AccountId:function:$self:service-$self:custom.stage-scheduler"
ResultPath: "$.iterator"
Next: "IsCountReached"
IsCountReached:
Type: Choice
Choices:
- Variable: "$.iterator.continue"
BooleanEquals: true
Next: "Wait"
Default: "Done"
Wait:
Type: Wait
Seconds: 1
Next: "Iterator"
Done:
Type: Pass
End: true
resources:
Outputs:
SchedulerStateMachine:
Description: The ARN of the state machine
Value:
Ref: SchedulerStateMachine
scheduler.py
import os
import boto3
lambda_client = boto3.client('lambda')
step_functions_client = boto3.client('stepfunctions')
def start(event, context):
step_functions_client.start_execution(stateMachineArn=os.environ['STATEMACHINE_ARN'])
return
def handle(event, context):
index = event['iterator']['index'] + 1
lambda_client.invoke(
FunctionName=os.environ['PUSH_FUNCTION'],
InvocationType='Event'
)
return
'index': index,
'continue': index < event['iterator']['count'],
'count': event['iterator']['count']
def push(event, context):
print("Executed every seconds!")
return
【讨论】:
需要注意的是,step 函数会在其执行历史日志中有 25k 个条目后自动停止(失败状态)。对于具有许多状态的阶跃函数,这可能会很快发生。 docs.aws.amazon.com/step-functions/latest/dg/… 这里适用吗?o avoid reaching this quota for long-running executions, implement a pattern that uses an AWS Lambda function that can start a new execution of your state machine
-> 这正是我在这里所做的,每分钟重新开始。
我已经运行了一年,它从未停止过,所以可以说@MarcSmith 的评论在这里不适用。【参考方案5】:
假设重试或轻微的时间漂移不是世界末日。另一种可能的方法是每分钟 cron 一次编排 lambda,然后转身并创建延迟的 sqs 消息。然后,您可以使用 sqs lambda 触发器来调用您的目标 lambda。
使用 SQS SendMessage DelaySeconds API(它可能是所有 AWS sdk 的原生 API)作为想要进行的亚分钟调用次数的偏移量。例如,如果您想每 5 秒拨打一次电话,您将创建 12 条消息
delaySeconds: 00
delaySeconds: 05
delaySeconds: 10
delaySeconds: 15
...
使用这种方法,必须特别注意 sqs 的 lambda 调用和重试逻辑。如果多次尝试是一个问题,请确保设置 DLQ 并考虑使用 FIFO 队列。根据设计,AWS 可能会多次调用目标 lambda。请注意,标准 SQS 队列是:at-least-once delivery,而 FIFO 队列是:exactly-once processing。由于 CloudWatch 可能会在一分钟“之后”几秒钟调用编排 lambda,因此这种方法也可能会产生一些时间偏差。
https://aws.amazon.com/sqs/faqs/这种方法是否比长时间运行编排 lambda 甚至阶跃函数更好?嗯,这取决于很多事情。就我个人而言,我发现让 lambda 处于等待状态的想法很浪费,你必须为那个 lambda 大部分时间什么都不做,如果它是一个很大的 lambda,那么这些成本并不是微不足道的。与 sqs 集成相比,使用 step 函数似乎有点矫枉过正,而且设置要复杂得多。
至少对我来说,最好让它启动,通过 sqs 安排一组任务然后死掉。这比长时间运行的 lambda 更复杂,有一些必须解决的并发问题,但如果这是人们想要的,它就是“无服务器”。
尽管如此,lambda 并不是最适合所有事情的——如果这是一项“永远”的任务,请考虑使用 ECS/Fargate/EC2,因为它很有可能更便宜,最终也不那么复杂。
【讨论】:
【参考方案6】:Cron 只允许至少一分钟。您可以做的是编写一个带有无限循环的 shell 脚本来运行您的任务,然后休眠 5 秒。这样,您的任务将或多或少地每 5 秒运行一次,具体取决于任务本身需要多长时间。
但这听起来确实像是你在做一些你可能不应该做的事情。这感觉不对。
【讨论】:
虽然可以每 5 秒执行一次 Lambda 并且仍保留在免费层(假设 t2.small 或t2.micro
实例的成本。
没错,但我不必担心维护机器 - 安全性、可用磁盘空间、从错误中恢复、故障机器等。 FaaS 有其优势,即使它有点贵。【参考方案7】:
现在有一个使用 CloudWatch 事件规则的解决方法,它会每分钟触发一个 Step Function。然后,step 函数将触发给定次数的“迭代器”Lambda,它将调用您的 lambda。这是AWS blog post。
【讨论】:
每 10 秒调用一次:~$18 step function cost + lambda。每秒一次:~200 美元 + lambda 成本。当 lambda 运行约 400 毫秒时,这意味着您需要为 lambda 支付约 10 美元,为调用支付约 200 美元。相当昂贵的调度器【参考方案8】:无论何时调用 lambda,假设是 1 分钟。将其除以 5 秒,您可以在调用 lambda 时保持可配置。
然后让循环等待并在处理程序内每 5 秒重复一次。 这样您就不需要任何新的 lambda 和 lambda 调用费用。
【讨论】:
以上是关于每 5 秒调用一次 Lambda 函数的主要内容,如果未能解决你的问题,请参考以下文章