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

在AWS Lambda中用DuckDB直接访问S3 Parquet文件失败排查

问题:DuckDB在AWS Lambda中直接访问S3 Parquet文件报HTTP 400错误

我在AWS S3中存储了一个Parquet文件,路径为s3://bucket/file.parquet,并在AWS Lambda中编写了如下函数尝试通过DuckDB直接访问该文件:

import os
def lambda_handler(event, context):
    import duckdb
    con = duckdb.connect(database=':memory:', read_only=False)
    home_directory = "/tmp/duckdb/"
    if not os.path.exists(home_directory):
        os.mkdir(home_directory)

    con.query("SET home_directory='/tmp/duckdb/';")
    con.query("INSTALL 'httpfs';")
    con.query("LOAD 'httpfs';")
    con.query("SET s3_access_key_id='xxx';")
    con.query("SET s3_secret_access_key='xxx;")
    con.query("SET s3_region='us-east-1';")
    sql = "select * from read_parquet('s3://bucket/file.parquet') limit 5;"
    data = con.execute(sql).fetchall()
    print(data)

运行后出现以下错误:

{
  "errorMessage": "HTTP Error: HTTP GET error on 's3://bucket/file.parquet' (HTTP 400)",
  "errorType": "HTTPException",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 140, in lambda_handler\n    data = con.execute(sql).fetchall()\n"
  ]
}

将S3路径替换为HTTPS签名URL,或通过boto3把文件下载到Lambda容器后访问均正常。根据DuckDB文档,直接传入S3路径是支持的,请问为何会失败?


原因分析与解决方案

1. 凭证配置语法错误

原代码中SET s3_secret_access_key='xxx;语句末尾缺少闭合的单引号,导致DuckDB无法正确解析S3密钥,进而生成格式错误的请求,触发HTTP 400错误。这是最直接的问题。

2. 硬编码密钥的风险与替代方案

即使修复引号,硬编码密钥也存在泄露风险。在Lambda环境中,更推荐使用IAM执行角色授权:

  • 给Lambda的执行角色添加包含s3:GetObject权限的策略,目标资源指定为s3://bucket/file.parquet或整个桶。
  • DuckDB的HTTPFS扩展可以自动获取Lambda的IAM角色临时凭证,无需手动设置s3_access_key_id和s3_secret_access_key。

3. 修正后的示例代码

import os
import duckdb

def lambda_handler(event, context):
    con = duckdb.connect(database=':memory:', read_only=False)
    home_directory = "/tmp/duckdb/"
    
    if not os.path.exists(home_directory):
        os.mkdir(home_directory)

    con.query(f"SET home_directory='{home_directory}';")
    con.query("INSTALL 'httpfs';")
    con.query("LOAD 'httpfs';")
    # 仅配置区域,依赖Lambda执行角色权限
    con.query("SET s3_region='us-east-1';")
    
    sql = "select * from read_parquet('s3://bucket/file.parquet') limit 5;"
    data = con.execute(sql).fetchall()
    print(data)

4. 额外检查点

  • 确认S3桶的区域与代码中设置的s3_region一致,区域不匹配也可能导致请求错误。
  • 检查S3对象的权限设置,确保执行角色或配置的密钥拥有该对象的读取权限。

内容的提问来源于stack exchange,提问作者pass-by-ref

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 06:11:26