AWS Lambda Function URL调用触发两次执行问题求助
Lambda通过Function URL调用时触发两次执行的排查与解决
在AWS控制台测试Lambda函数时,函数仅执行一次;但通过Function URL调用该Lambda函数时,它会触发两次执行。相关代码如下:
import json import boto3 dynamodb = boto3.resource('dynamodb') ddbClient = boto3.client('dynamodb') def LatestDBrow(): ... return row #Invoke lambda function def lambda_handler(event, context): scratchPadlist = [] scratchPadlist = LatestDBrow() #print(scratchPadlist) #Put TS row into variables inBatchTrial = scratchPadlist[0] inNoOfUsersProcessed = scratchPadlist[1] inl1Alpha = scratchPadlist[2] inl1Beta = scratchPadlist[3] #Update wanted values inBatchTrial += 1 inl1Alpha = 1 inl1Beta = 1 TableColNames = ['Batch Trial','No. of users processed','L1 Alpha', 'L1 Beta','L1 N','L1 Rewards', 'L1 Click Pct','L2 Alpha','L2 Beta', 'L2 N','L2 Rewards','L2 Click Pct', 'Next Page Shown'] TSlist = [inBatchTrial, inNoOfUsersProcessed, inl1Alpha, inl1Beta, inl1N, inl1Rewards, inl1ClickPct, inl2Alpha, inl2Beta, inl2N, inl2Rewards,inl2ClickPct, innextPageShown] dbDict = {TableColNames[i]: str(TSlist[i]) for i in range(len(TableColNames))} table1 = dynamodb.Table("TestDB") table1.put_item(Item = dbDict)
可能的原因及解决方向
1. 浏览器跨域预检请求(OPTIONS)
当浏览器发起跨域请求时,会先发送一个OPTIONS请求确认权限,如果你的Lambda没处理这种请求,会被当成正常请求执行业务逻辑,加上后续的实际请求就会触发两次。
解决方法:在lambda_handler开头判断请求方法,遇到OPTIONS直接返回允许跨域的响应,跳过业务逻辑:
def lambda_handler(event, context): # 处理OPTIONS预检请求 http_method = event.get('requestContext', {}).get('http', {}).get('method') if http_method == 'OPTIONS': return { 'statusCode': 200, 'headers': { 'Access-Control-Allow-Origin': '*', # 按需替换成指定域名 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type' } } # 原有业务逻辑...
2. 客户端重复发起请求
调用Function URL的客户端可能因为超时、未收到响应自动重试,或者网络波动导致请求重发。比如前端代码没做防抖、请求超时设置过短,都会导致两次请求。
解决方法:
- 客户端侧:添加请求防抖机制,设置合理的超时时间,确保只发送一次请求;
- Lambda侧:添加幂等性处理,比如用请求ID或业务唯一标识(比如
Batch Trial值)作为判断,避免重复执行写入操作。
3. Lambda未返回有效响应触发重试
你的代码里lambda_handler没有返回任何响应,Function URL会认为请求失败,进而触发重试逻辑,导致函数执行两次。
解决方法:在函数末尾添加标准HTTP响应返回:
def lambda_handler(event, context): # 原有业务逻辑... table1.put_item(Item = dbDict) # 返回有效响应 return { 'statusCode': 200, 'body': json.dumps({'message': '数据更新成功'}) }
4. 业务逻辑的竞态条件(可能性较低)
如果LatestDBrow函数的查询逻辑存在竞态,比如两次请求同时获取到相同的旧数据,可能会让你误以为函数执行了两次,但结合控制台测试正常,这个概率不高。可以检查LatestDBrow的实现,或者给DynamoDB的put_item添加条件表达式,比如:
table1.put_item( Item = dbDict, ConditionExpression = 'attribute_not_exists(#batch) OR #batch = :current_batch', ExpressionAttributeNames = {'#batch': 'Batch Trial'}, ExpressionAttributeValues = {':current_batch': str(inBatchTrial)} )
内容的提问来源于stack exchange,提问作者Alan Chow
相关产品推荐
相关产品推荐

