我可以使用lambda函数调度lambda函数执行吗?

时间:2017-02-21 02:54:14

标签: amazon-web-services aws-lambda

我正在寻找以编程方式安排lambda函数与另一个lambda函数运行一次的能力。例如,我使用myFirstFunctiondate参数向time发出了请求,然后在该日期和时间执行mySecondFunction。这只能用于无状态AWS服务吗?我试图避免一个永远在线的ec2实例。

我发现调度lambda函数的大部分结果都与cloudwatch和定期调度的事件有关,而不是ad-hoc事件。

7 个答案:

答案 0 :(得分:3)

这是 aws step functions 的完美用例。

Wait 状态与 SecondsPathTimestampPath 结合使用以在执行下一个状态之前添加所需的延迟。

答案 1 :(得分:1)

更新 - 我不建议使用这种方法。当TTL删除发生并且它们不接近TTL时间时,情况发生了变化。唯一的保证是在TTL之后将删除该项目。感谢@Mentor强调这一点。

2个月前,AWS宣布了DynamoDB项目TTL,它允许您插入项目并标记何时删除它。它会在时机成熟时自动删除。

您可以将此功能与DynamoDB Streams结合使用以实现您的目标 - 您的第一个功能是将项目插入DynamoDB表。记录TTL应该是您想要触发第二个lambda的时间。设置一个触发第二个lambda的流。在这个lambda中,你将识别删除事件,如果这是删除,那么运行你的逻辑。

奖励点 - 您可以使用表项作为第一个lambda将参数传递给第二个lambda的机制。

关于DynamoDB TTL: https://aws.amazon.com/blogs/aws/new-manage-dynamodb-items-using-time-to-live-ttl/

答案 2 :(得分:1)

如果您想同时运行第二个功能,请使用AWS开发工具包的invoke()类的Lambda方法。使用调用类型Event时,您会忘记通话。

如果要在几分钟后运行第二个函数,则应使用CloudWatch Events规则安排lambda函数每隔x分钟运行一次,但请禁用该规则。在第一个函数中,使用enableRule()类的AWS开发工具包的CloudWatchEvents方法以编程方式启用规则。然后在预定的函数中,选中enableRule()来禁用自身。

答案 3 :(得分:0)

我选择在myFirstFunction中使用message timers将延期工作排入SQS。

目前,您不能将SQS用作Lambda事件源,但您可以定期安排mySecondFunction通过计划的CloudWatch Events检查队列(有些是您找到的其他选项的变体)或使用CloudWatch在ApproximateNumberOfMessagesVisible上发出警报以向Lambda发送SNS消息,并避免对长时间不经常处于非活动状态的队列进行持续轮询。

答案 4 :(得分:0)

您要做的事情(从Lambda安排Lambda)使用当前的AWS服务是不可能的。

因此,为了避免永远在线的ec2实例,还有其他选择:

1)使用AWS默认或自定义指标。例如,您可以使用ApproximateNumberOfMessagesVisibleCPUUtilization(如果您的应用在处理请求时触发大量CPU利用率)。您还可以创建自定义指标,并在实例空闲时触发它(具体取决于您在实例中运行的应用)。

此选项的问题在于您将浪费已支付的会议记录(无论您是否使用实例15分钟,AWS总是收取一整小时的费用)。

2)在我看来,更好的选择是每分钟运行一次Lambda函数,检查你的实例是否空闲,只有当它们接近整个小时才关闭它们。

import boto3
from datetime import datetime

def lambda_handler(event, context):
    print('ManageInstances function executed.')
    environments = [['instance-id-1', 'SQS-queue-url-1'], ['instance-id-2', 'SQS-queue-url-2'], ...]
    ec2_client = boto3.client('ec2')
    for environment in environments:
        instance_id = environment[0]
        queue_url = environment[1]
        print 'Instance:', instance_id
        print 'Queue:', queue_url
        rsp = ec2_client.describe_instances(InstanceIds=[instance_id])
        if rsp:
            status = rsp['Reservations'][0]['Instances'][0]
            if status['State']['Name'] == 'running':
                current_time = datetime.now()
                diff = current_time - status['LaunchTime'].replace(tzinfo=None)
                total_minutes = divmod(diff.total_seconds(), 60)[0]
                minutes_to_complete_hour = 60 - divmod(total_minutes, 60)[1]
                print 'Started time:', status['LaunchTime']
                print 'Current time:', str(current_time)
                print 'Minutes passed:', total_minutes
                print 'Minutes to reach a full hour:', minutes_to_complete_hour
                if(minutes_to_complete_hour <= 2):
                    sqs_client = boto3.client('sqs')
                    response = sqs_client.get_queue_attributes(QueueUrl=queue_url, AttributeNames=['All'])
                    messages_in_flight = int(response['Attributes']['ApproximateNumberOfMessagesNotVisible'])
                    messages_available = int(response['Attributes']['ApproximateNumberOfMessages'])
                    print 'Messages in flight:', messages_in_flight
                    print 'Messages available:', messages_available
                    if(messages_in_flight + messages_available == 0):
                        ec2_resource = boto3.resource('ec2')
                        instance = ec2_resource.Instance(instance_id)
                        instance.stop()
                        print('Stopping instance.')
            else:
                print('Status was not running. Nothing is done.')
        else:
            print('Problem while describing instance.')

答案 5 :(得分:0)

我想也许你可以使用these instructions

但我已尝试过这些说明,除非我手动进入控制台将规则与目标相关联,否则它无法正常工作。 (尽管发送了API调用put_target

另外,我不明白这些说明的最后一步是什么。我没有这样做,因为它似乎不适用,但也许这就是为什么我的工作不起作用。

答案 6 :(得分:0)

这的确取决于您的用例,但是您想稍后触发某事的想法是一种常见的模式。我无服务器的方式是有一个React应用程序,该应用程序会触发将来存储日期的操作。我采用了类似于24-12-2020的日期格式,然后使用date()对其进行了转换,研究了提到的日期格式是正确的,因此我可以尝试使用12-24-2020看看我得到了什么!当我高兴时,我将其转换为javascript React中的Unix编号,我使用以下代码:

new Date(action.data).getTime() / 1000

其中action.data是操作的日期,也许是时间。

我在Amplify(无服务器)中运行React,然后将其存储到dynamodb(无服务器)中。然后,我运行Lambda函数(无服务器)以检查我的dynamodb是否存在任何日期(我现在实际使用Unix时间),然后立即比较这两个Unix日期(存储的),它们都是数字,因此比较容易。在我看来,这是非常容易且非常可靠的。

我只是根据所需的近似频率将Lambda上的crontab设置为所需的值,在大多数情况下,每五分钟运行一次Lambda是相当不错的,尽管如果我只是在某个特定时间段内进行业务操作平日的应用程序,我将控制Lambda多一点。 Lambda每月免费提供前100万个功能,每隔几分钟运行一次Lambda无需花费任何费用。显然情况发生了变化,因此您需要在您所在的地区进行查找。

在这种情况下,您永远不会获得完美的时机。但是,由于根据Lambda函数的计时设置,绝大多数用例都足够接近,因此您可以将其设置为每分钟或每天检查一次,这完全取决于您的应用程序。

或者,如果我想对事件进行即时反应,则可以使用SMS,SQS或Kinesis即时流式传输消息,这完全取决于您的用例。