You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 04:20:28