我有一个超时为 900 秒(15 分钟)的 AWS Lambda 函数。它被设置为使用 EventBridge 计划每 20 分钟运行一次。另外,在代码中,有一个逻辑,一旦达到 14 分钟的运行时间,就会结束该函数。它运行得很完美。
然后,我将该函数的保留并发限制更改为 15,并将 EventBridge 时间表更改为每一分钟。这就是事情开始变得奇怪的地方。
该函数每隔一分钟触发一次,但一旦达到 15 个并发执行,它似乎就停止执行 lambda_handler 函数中包含的代码。然后并发执行数从15个下降到1个。我说的函数代码没有被执行的意思是这样的:
注意整个执行过程花费了 1.74 毫秒。我在 lambda_handler() 的正下方放置了一条 print() 语句,以查看它是否已执行,但它甚至没有执行到那么远。看起来好像该函数被调用,但其中的任何代码都没有被执行。有趣的是,如果我更新函数并重新部署,它会再次恢复正常运行并执行代码。这表明冷启动工作正常,但热实例行为不正确。
我启用了 X 射线,它真正显示的是函数执行持续了 2 毫秒。还有什么可以看的吗?
任何想法将不胜感激。谢谢。
更新1(Lambda函数代码)
注意 - 我隐藏了 process_symbol() 的实现,因为它只是下载股票代码的数据并将其保存到 S3。
import os
import json
import s3fs
import urllib3
from datetime import datetime
MAX_RUNNING_TIME_SECONDS = 900
# Timing
start_execution_time = datetime.now()
def get_execution_time_remaining():
return MAX_RUNNING_TIME_SECONDS - (datetime.now() - start_execution_time).seconds
def lambda_handler(event, context):
print('Execution beginning')
symbols = []
execution_time_remaining = get_execution_time_remaining()
while execution_time_remaining > 60:
# Get next symbol to load
symbol_metadata = get_next_symbol_to_load()
if symbol_metadata:
symbol = symbol_metadata[0]
symbols.append(symbol)
# process_symbol(symbol)
# update_rds(symbol)
execution_time_remaining = get_execution_time_remaining()
print(f'execution_time_remaining = {execution_time_remaining}')
return_message = ''
current_time_text = datetime.now().strftime('%m/%d/%Y, %H:%M:%S.%f')
if symbols:
return_message = f"Successfully saved {', '.join(symbols)} to the cloud at {current_time_text}."
else:
return_message = f'Successfully execution at {current_time_text} but no symbols were processed.'
return {
"statusCode": 200,
"body": return_message,
}
更新2
还值得注意的是,在它增加到 15 个并发执行并停止执行 lambda 函数中包含的代码后,会有大约 80-90 分钟的休息时间,然后才会以某种方式再次开始执行函数代码。
正如 @Maurice 暗示的那样,有一个全局变量会影响并发场景中代码的执行。作业:
start_execution_time = datetime.now()
之前分配在 lambda_handler() 上方,当移动到其中时,导致并发按预期工作。这篇博文也很有用:
https://pfisterer.dev/posts/aws-lambda-container-reuse/
它讨论了 lambda 如何重用容器以及这可能对执行产生什么影响。