【问题标题】:AWS python SDK invoking AWS lambda function more than onceAWS python SDK 多次调用 AWS lambda 函数
【发布时间】:2020-02-24 07:37:30
【问题描述】:

我正在使用 python SDK 从另一个 lambda 调用一个 lambda。两个 lambda 都属于同一个 VPC。触发器 lambda 仅包含一个调用第二个 lambda (loader_development) 的 python 脚本,其代码如下:

from __future__ import print_function

import json
import logging
import os
from urllib2 import urlopen,Request,HTTPError
import boto3

logger = logging.getLogger()
logger.setLevel(logging.INFO)
region = os.environ['AWS_REGION']

def lambda_handler(event, context):
    logger.info('starting loading')
    invokeLambda = boto3.client('lambda', region_name = 'us-east-1')  
    request = {'resource':'/bucketstatus/latest','path':'/bucketstatus/latest','httpMethod':'GET', 'requestContext': {'requestId': context.aws_request_id,'identity': {'userArn': context.invoked_function_arn}}}
    invoke_response = invokeLambda.invoke(FunctionName='loader_development',
                                           InvocationType='RequestResponse',
                                           Payload=json.dumps(request))
    print(invoke_response['Payload'].read())

logger.info('Process Complete')

我在上面的代码中遇到了问题。所以我现在面临的问题是这个脚本不止一次触发 loader_development lambda,这会在我的数据库中创建冗余条目(例如:我的数据库中应该只有 6 个条目,但可能是由于多个 lambda 调用导致根据脚本,大约创建了 19 个条目)。

通过分析触发器的 CloudWatch 日志,我了解到它会创建与加载程序 lambda 的 HTTPS 连接并等待响应。如果它没有收到响应,它会再次尝试创建一个新的 HTTPS 连接。我可以在一个日志中看到这三遍。我也贴在这里。

[DEBUG] 2019-10-25T16:00:05.155Z 0342a98d-1cee-474a-9147-b90c4a804c4c Starting new HTTPS connection (1): lambda.us-east-1.amazonaws.com:443
[DEBUG] 2019-10-25T16:01:05.298Z 0342a98d-1cee-474a-9147-b90c4a804c4c Event needs-retry.lambda.Invoke: calling handler <botocore.retryhandler.RetryHandler object at 0x7f8588337b90>
[DEBUG] 2019-10-25T16:01:05.299Z 0342a98d-1cee-474a-9147-b90c4a804c4c retry needed, retryable exception caught: Read timeout on endpoint URL: "https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/loader_development/invocations"
Traceback (most recent call last):
File "/var/runtime/botocore/retryhandler.py", line 269, in _should_retry
return self._checker(attempt_number, response, caught_exception)
File "/var/runtime/botocore/retryhandler.py", line 317, in __call__
caught_exception)
File "/var/runtime/botocore/retryhandler.py", line 223, in __call__
attempt_number, caught_exception)
File "/var/runtime/botocore/retryhandler.py", line 359, in _check_caught_exception
raise caught_exception
ReadTimeoutError: Read timeout on endpoint URL: "https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/loader_development/invocations"
[DEBUG] 2019-10-25T16:01:05.316Z 0342a98d-1cee-474a-9147-b90c4a804c4c Retry needed, action of: 0.421144501955
[DEBUG] 2019-10-25T16:01:05.316Z 0342a98d-1cee-474a-9147-b90c4a804c4c Response received to retry, sleeping for 0.421144501955 seconds
[DEBUG] 2019-10-25T16:01:05.738Z 0342a98d-1cee-474a-9147-b90c4a804c4c Event request-created.lambda.Invoke: calling handler <bound method RequestSigner.handler of <botocore.signers.RequestSigner object at 0x7f8587af6b90>>
[DEBUG] 2019-10-25T16:01:05.738Z 0342a98d-1cee-474a-9147-b90c4a804c4c Event choose-signer.lambda.Invoke: calling handler <function set_operation_specific_signer at 0x7f85887c8398>

上述一组日志在同一日志下出现至少 3 次。我如何告诉脚本不要多次创建 HTTPS 连接,因为这会导致多次调用,并且 loader_development lambda 大部分时间都在忙于尝试处理较旧的请求,因此有时某些实体未成功更新在我的数据库中。请告诉我。谢谢!

更新:我在触发器中添加了以下解决方案,但现在“开始加载”正在打印三次,所以我认为这个脚本被调用了三次。以前只有 loader_development lambda 被重试。(仅供参考:我为触发 cron(0/30 7-9 * * ? *) 启用了 cloudwatch 事件,所以 cloudwatch 事件也有重试机制?)

附:如果我没有计划的 cloudwatch 事件来触发此脚本,则以下解决方案有效。

【问题讨论】:

    标签: python-2.7 amazon-web-services aws-lambda boto3


    【解决方案1】:

    问题归咎于boto3调用API内置重试。根据invoke documentation

    发生错误时,您的函数可能会被多次调用。 重试行为因错误类型、客户端、事件源和 调用类型。例如,如果您异步调用一个函数 它返回一个错误,Lambda 最多执行两个函数 次。有关详细信息,请参阅重试行为。

    您可以尝试实施以下建议

    https://github.com/boto/boto3/issues/1104#issuecomment-385045896

    import boto3
    import botocore.config
    
    cfg = botocore.config.Config(retries={'max_attempts': 0})
    client = boto3.client('lambda', config=cfg)
    

    【讨论】:

    • 好的,让我试试这个然后回来。谢谢!
    • 嘿!是的,我有 99% 的把握做到了。为了更加确定,我再次触发了我的脚本。
    • 好的,这并没有解决我的问题。它仍在使用 lambda 创建 3 个 HTTPS 连接。我在全局而不是在我的 lambda_handler 函数中给出了 cfg 变量。会不会是个问题。我需要在函数内部提供 cfg 吗?
    • https://hackernoon.com/simple-steps-to-avoid-the-retry-behavior-from-aws-lambda-su4w63yx9 回答了我关于 cloudwatch 事件的第二个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-19
    • 2017-10-03
    • 2022-01-27
    • 2016-01-29
    • 2022-01-17
    • 2021-12-09
    • 1970-01-01
    相关资源
    最近更新 更多