我正在使用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启用了 cloudwatch事件(0/30 7-9 * *?*),因此cloudwatch事件也可以重试机制?)
P.S。如果我没有安排的cloudwatch事件触发此脚本,则以下解决方案有效。
答案 0 :(得分:2)
该问题归咎于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)