Lambda中已运行EC2实例状态始终返回pending的原因排查
问题根因
这个现象是两个机制叠加导致的:
- Lambda执行环境复用:短时间内多次触发Lambda时,平台会直接复用之前冷启动生成的运行环境,不会重新初始化写在全局作用域的boto3资源对象,旧的EC2实例资源对象会一直保留在复用环境中。
- boto3高等级Resource对象自带本地缓存:创建的EC2 Instance资源对象,第一次访问
state属性时会调用接口拉取一次实例数据存储在本地,之后再访问这个属性,默认不会重新向AWS服务端发起请求,直接返回本地存储的旧数据。
调用instance.start()之后,本地缓存的状态就停留在pending对应的码值0,哪怕EC2控制台已经显示实例进入运行状态,只要不手动刷新资源对象,读到的永远是缓存里的旧值。重新部署Lambda函数后,下次触发会走全新的冷启动流程,重新创建EC2资源对象,第一次拉取状态时就能拿到最新的running对应码值16,就会表现为"重新部署后才正常"。
修复方法
每次读取实例状态前,手动调用reload()方法强制拉取服务端最新数据,覆盖本地缓存:
# 强制刷新实例最新属性 instance.reload() # 读取最新状态码 code = instance.state['Code']
如果不想手动加刷新逻辑,也可以把EC2实例对象的初始化逻辑移到Lambda的handler处理函数内部,每次函数触发都新建一个资源对象,同样能避开旧缓存的影响,两种方式性能差异极小,按需选择即可。
内容的提问来源于stack exchange,提问作者Sir Galan
相关产品推荐
相关产品推荐

