ThreadPoolExecutor线程未计入耗时问题排查
AWS Lambda多线程调用额外耗时分析
问题背景
现有一个AWS Lambda函数,通过多线程调用另一个Lambda函数,每个子线程的耗时均不超过1.4秒,但所有线程完成汇合的总耗时却达到了约2.5秒,比单个线程的最长耗时多出约1秒,请问这部分额外消耗的时间用于何处?
父Lambda函数代码
import boto3 import json import concurrent.futures from stats import Timer client = boto3.client('lambda') def do_lambda(): timer = Timer() response = client.invoke( FunctionName = 'arn:aws:lambda:us-east-1:497857710590:function:wherewasit-search', InvocationType = 'RequestResponse', Payload = json.dumps({'keys': 1})) payload = json.loads(json.load(response['Payload'])['body']) print(f"Response after {timer.stop()}ms") def do_work(n_threads): timer = Timer() with concurrent.futures.ThreadPoolExecutor() as executor: futures = [] for i in range(n_threads): futures.append(executor.submit(do_lambda)) for future in concurrent.futures.as_completed(futures): pass print(f"Joined all: {timer.stop()}ms") def lambda_handler(event, context): do_work(9) return { 'statusCode': 200, 'body': json.dumps('Hello from Lambda!') }
运行输出
Response after 1236ms Response after 1242ms Response after 1251ms Response after 1272ms Response after 1322ms Response after 1359ms Response after 1126ms Response after 1170ms Response after 1246ms Joined all: 2496ms
额外耗时的核心原因分析
1. 目标Lambda的并发执行限制与排队延迟
你调用的wherewasit-search函数存在并发执行上限(默认账户并发数为1000,但单个函数的并发数受限于自身配置和AWS动态调度)。当同时发起9个调用时,如果该函数当前没有足够的空闲执行环境,部分请求会进入等待队列,直到已有执行环境释放后才能开始执行。这部分排队时间会直接叠加到总汇合时间中,导致总耗时远超单个线程的最长耗时。
2. 父Lambda的资源受限导致线程调度开销
Lambda运行环境的CPU、内存资源与配置的内存大小绑定,内存越小,CPU配额越低。如果父Lambda的内存配置较低,同时运行9个线程时,线程之间会竞争有限的CPU时间片和网络IO资源,导致线程执行、IO操作被延迟,整体汇合时间被拉长。
3. boto3客户端的连接与调度开销
boto3的Lambda客户端使用连接池管理请求,短时间内发起大量并发调用时,连接池的初始化、连接复用会产生额外开销。同时,AWS内部服务间的请求调度、网络传输延迟在并发场景下会被累积放大,这部分延迟在单个请求中不明显,但会增加总汇合时间。
排查验证建议
- 查看
wherewasit-search函数的CloudWatch日志,对比每个请求的Init Duration和Duration,以及请求的开始时间,确认是否存在排队等待的情况。 - 提高父Lambda的内存配置(比如调整到1024MB或更高),观察总耗时变化,判断是否是资源受限导致。
- 给
wherewasit-search函数设置预留并发,确保有足够的执行环境处理并发请求,再测试总耗时是否下降。
内容的提问来源于stack exchange,提问作者AlwaysLearning
相关产品推荐
相关产品推荐

