如何处理python lambda中的超时?

Moj*_*imi 5 amazon-web-services aws-lambda python-3.7

我知道以前有人对此提出过质疑,但没有提出真正的解决方案,我想知道现在是否有任何新方法。

无论如何,是否可以使用任何 AWS 服务挂钩事件来检查 lambda 是否已超时?我的意思是它登录到它超时的 CloudWatch 日志中,所以必须有办法。

特别是在 Python 中,因为它并不像使用 Javascript 和其他自然并发语言那样持续检查它是否达到 20 分钟标记那么简单。

理想情况下,如果 python lambda 超时,我想执行一个 lambda,并使用与原始接收相同的负载。

小智 15

我想更新 @John Rotenstein 的答案,该答案对我有用,但导致填充 cloudwatch 日志时出现以下错误:

START RequestId: ********* Version: $LATEST
Traceback (most recent call last):
    File "/var/runtime/bootstrap", line 9, in <module>
    main()
    File "/var/runtime/bootstrap.py", line 350, in main
    event_request = lambda_runtime_client.wait_next_invocation()
    File "/var/runtime/lambda_runtime_client.py", line 57, in wait_next_invocation
    response = self.runtime_connection.getresponse()
    File "/var/lang/lib/python3.7/http/client.py", line 1369, in getresponse
    response.begin()
    File "/var/lang/lib/python3.7/http/client.py", line 310, in begin
    version, status, reason = self._read_status()
    File "/var/lang/lib/python3.7/http/client.py", line 271, in _read_status
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
    File "/var/lang/lib/python3.7/socket.py", line 589, in readinto
    return self._sock.recv_into(b)
    File "/var/task/lambda_function.py", line 6, in timeout_handler
    raise Exception('Time limit exceeded')
Exception: Time limit exceeded
END RequestId
Run Code Online (Sandbox Code Playgroud)

所以我只需要在返回每个响应之前重置信号警报:

import logging
import signal


def timeout_handler(_signal, _frame):
    raise Exception('Time limit exceeded')


signal.signal(signal.SIGALRM, timeout_handler)


def lambda_handler(event, context):
    try:
        signal.alarm(int(context.get_remaining_time_in_millis() / 1000) - 1)

        logging.info('Testing stuff')
        # Do work

    except Exception as e:
        logging.error(f'Exception:\n{e}')

    signal.alarm(0)# This line fixed the issue above!
    return {'statusCode': 200, 'body': 'Complete'}
Run Code Online (Sandbox Code Playgroud)


Joh*_*ein 10

这是来自cloudformation-custom-resources/lambda/python · GitHub的示例展示了用 Python 编写的 AWS Lambda 函数如何意识到它即将超时。

(我已经编辑了其他内容,这是相关的部分):

import signal

def handler(event, context):

    # Setup alarm for remaining runtime minus a second
    signal.alarm((context.get_remaining_time_in_millis() / 1000) - 1)

    # Do other stuff
    ...

def timeout_handler(_signal, _frame):
    '''Handle SIGALRM'''
    raise Exception('Time exceeded')

signal.signal(signal.SIGALRM, timeout_handler)
Run Code Online (Sandbox Code Playgroud)


alf*_*sin 2

我能想到的两个选择,第一个是快速和肮脏的,但也不太理想:

  1. 在步骤函数中运行它(查看AWS中的步骤函数),该函数能够在超时/错误时重试

  2. 更好的方法是将代码重新架构为幂等。在此示例中,触发 lambda 的流程会检查一个条件,只要该条件为真,就会触发 lambda。除非 lambda 成功执行完逻辑,否则该条件需要保持为 true。例如,这可以通过将发送到 lambda 的参数保存在数据库的表中来获得,并且有一个名为“processed”的额外字段,仅当 lambda 成功完成该事件的运行后,该字段才会被修改为“true”。

使用方法 #2 将使您的代码更具弹性,易于在出现错误时重新运行,并且也易于监控:基本上您所要做的就是检查有多少此类未处理的记录,以及它们的创建/内容是什么更新数据库上的时间戳。