提问人:Jonathan Garvey 提问时间:11/12/2023 最后编辑:Jonathan Garvey 更新时间:11/13/2023 访问量:97
AWS Lambda 将并发执行次数增加到 15 次,然后在lambda_handler内停止执行代码,然后降至 1 次并发执行
AWS Lambda ramps up to 15 concurrent executions and then stops executing code inside lambda_handler before dropping to 1 concurrent execution
问:
我有一个超时 900 秒(15 分钟)的 AWS Lambda 函数。它被设置为使用 EventBridge 计划每 20 分钟运行一次。此外,在代码中,有逻辑,一旦达到 14 分钟的运行时间,它就会结束函数。它运行得很完美。
然后,我将函数的预留并发限制更改为 15,并将 EventBridge 计划更改为每 1 分钟一次。这就是它开始变得奇怪的地方。
该函数每一分钟触发一次,但一旦达到 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 如何重用容器以及这可能对执行产生什么影响。
评论
Execution beginning