【问题标题】:Trouble using python request module to make API post call within AWS lambda使用 python 请求模块在 AWS lambda 中进行 API 发布调用时遇到问题
【发布时间】:2016-12-29 21:08:08
【问题描述】:

在我的 lambda 执行函数开始连接到必要的 AWS 资源后,我有一个 lambda_handler 函数,如下所示:

def lambda_handler(event, context, dst):

    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.unquote_plus(event['Records'][0]['s3']['object']['key'].encode('utf8'))
    print('Bucket: %s' % bucket)
    print('Object key: %s' % key)

    crm_file_name = key.split('/')[-1]
    crm_query = make_crm_db_query(crm_file_name)
    cur = conn.cursor()
    status = cur.execute(crm_query)

    if status == 1:
        details = cur.fetchone()
        opportunity_id = details[0]

        tmp = dst.get_key('%s/%s' % (opportunity_id, crm_file_name))
        print('starting API request...')
        s = requests.Session()
        r = s.post('http://link/to/endpoint/',\
            files={'pdf': tmp}, data={'opportunity_id': opportunity_id})
        print(r)
        print(r.content)
    else:
        print('not the right file type')

在我的开发环境中返回如下,说明发帖成功:

starting API request...
<Response [201]>
{"opportunity_id":253,"pdf":"https://s3.storage.asset.com:443/253/253___PDF.pdf?Signature=[CONFIDENTIAL STUFF HERE ;)]"}

在 AWS Cloud Watch 日志中,但是在尝试执行发布请求时进程挂起。这是一个日志示例:

starting API request...
END RequestId: beedb0c4-ce07-11e6-a715-53b3bd8edccc
REPORT RequestId: beedb0c4-ce07-11e6-a715-53b3bd8edccc  Duration: 30002.89 ms   Billed Duration: 30000 ms Memory Size: 128 MB   Max Memory Used: 22 MB  
2016-12-29T20:46:24.356Z beedb0c4-ce07-11e6-a715-53b3bd8edccc Task timed out after 30.00 seconds 

S3 存储桶、API 端点和 RDS 都属于同一个 VPC。该过程在开发中有效,但在生产中挂起。关于如何调试的任何指示?

我检查了this post,它说与外部 Internet 资源的连接需要 NAT 网关,但我们的 API 端点在同一 VPC 内的 EC2 实例上运行。 AWS 是否认为我们仍在尝试建立外部连接,因为我们正在处理 API 调用?我该如何调试?

【问题讨论】:

  • 从局外人的角度来看,离开这里还不够。我会仔细检查您的开发和产品设置之间的差异......并确保您所做的任何假设都是正确的。
  • 您需要确保您使用的是运行 API 的 EC2 服务器的私有 IP。如果您使用的是公共 IP,它将被视为存在于 VPC 之外的资源。另外,您是否打开了 EC2 服务器所属的安全组,以允许从 Lambda 函数访问(通过 Lambda 函数所属的安全组的 ID)?
  • @MarkB:这真的很有帮助,谢谢,我担心它可能是这样的。问题是我们正在使用 Jenkins 配置的 EC2 实例上运行应用程序。负载平衡器读取传入请求的标头,然后根据公共域名调用适当的应用程序。如果我们切换到私有 IP,那么负载均衡器将不知道要调用哪个应用程序。听起来我们可以自定义负载均衡器规则(不确定它有多容易)或创建一个专用实例。你怎么看?
  • 听起来是对的。其他选项是将 NAT 网关添加到您的 VPC,或者在 Route53 中设置一个私有托管区域,将这些 DNS 名称解析为内部私有 IP。
  • @MarkB:太棒了,感谢您帮助我解决这个问题。如果你想把它写成一个快速的答案,我很乐意选择它。

标签: python amazon-s3 python-requests aws-lambda nat


【解决方案1】:

我遇到了同样的timeout problem,原因如下。

AWS document:

当您将 VPC 配置添加到 Lambda 函数时,它只能访问该 VPC 中的资源。如果 Lambda 函数需要访问 VPC 资源和公共 Internet,则 VPC 需要在 VPC 内部具有网络地址转换 (NAT) 实例。

Mark B 的评论是对的。

我建议你可以按照blog 来构建 NAT。

【讨论】:

  • 谢谢,@Jimlin,你和 Mark B 都在现场。 VPC 是解决此问题的最简单方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-19
  • 1970-01-01
  • 2019-05-18
  • 2019-10-03
  • 2020-02-08
  • 2020-03-24
  • 1970-01-01
相关资源
最近更新 更多