Lambda复制S3文件超21个时卡顿超时的原因排查
问题原因分析
1. aioboto3客户端连接池上限限制
aioboto3(基于boto3)的S3客户端默认存在连接池大小限制(通常默认值在10-20区间),当同时发起的异步请求数量超过连接池容量时,多余请求会进入等待队列,等待空闲连接释放。当任务数量突破21时,等待队列中的请求会因等待时间过长,触发Lambda的30秒超时限制。
2. Lambda执行环境的资源瓶颈
Lambda执行环境有严格的资源配额:
- 网络连接数限制:每个Lambda执行环境的并发网络连接数有限,内存配置越低,连接数上限越低,大量并发S3请求会耗尽可用连接,导致请求阻塞。
- CPU/内存资源不足:若Lambda配置的内存较小(比如128MB),同时处理大量异步任务会导致CPU使用率飙升,任务执行速度骤降,最终触发超时。
3. 无并发控制的批量异步请求
代码中直接通过asyncio.gather(*tasks)一次性发起所有复制任务,未做并发数限制。当任务数量过多时,不仅会打满客户端连接池,还会给Lambda执行环境带来过大资源压力,进而引发卡顿和超时。
解决方案建议
- 限制并发请求数:使用
asyncio.Semaphore控制同时执行的复制任务数量,避免超过连接池和Lambda资源上限:
async def copy_images_for_new_guide( keys: list[str], new_guide_id: int, org_id: int, ) -> None: session = aioboto3.Session() # 设置并发数上限,可根据实际情况调整 semaphore = asyncio.Semaphore(15) async def bounded_copy(key): async with semaphore: new_key = f"orgs/org_{org_id}/guide_{new_guide_id}/{key.split('/')[-1]}" await _copy_image( s3_client, key, new_key, variables.settings.IMAGES_BUCKET ) async with session.client( "s3", region_name=variables.secrets.AWS_REGION_NAME, ) as s3_client: tasks = [bounded_copy(key) for key in keys] await asyncio.gather(*tasks)
- 调整Lambda资源配置:提升Lambda的内存配置(比如调整到256MB或更高),内存提升会同步增加CPU和网络资源配额,缓解资源瓶颈。
- 显式设置S3客户端连接池大小:初始化S3客户端时,通过
config参数增大连接池上限:
from botocore.config import Config async with session.client( "s3", region_name=variables.secrets.AWS_REGION_NAME, config=Config(max_pool_connections=50) ) as s3_client: # 后续业务代码
内容的提问来源于stack exchange,提问作者Nikolaisyl
相关产品推荐
相关产品推荐

