Amazon web services 尝试在AWS上的lambda中调用pycurl时出错

Amazon web services 尝试在AWS上的lambda中调用pycurl时出错,amazon-web-services,aws-lambda,layer,pycurl,Amazon Web Services,Aws Lambda,Layer,Pycurl,我想使用pycurl来拥有TTFB和TTLB,但我无法在AWS lambda中调用pycurl 为了关注这个问题,假设我调用这个简单的lambda函数: import json import pycurl import certifi def lambda_handler(event, context): client_curl = pycurl.Curl() client_curl.setopt(pycurl.CAINFO, certifi.where()) cli

我想使用pycurl来拥有TTFB和TTLB,但我无法在AWS lambda中调用pycurl

为了关注这个问题,假设我调用这个简单的lambda函数:

import json
import pycurl
import certifi


def lambda_handler(event, context):
    client_curl = pycurl.Curl()
    client_curl.setopt(pycurl.CAINFO, certifi.where())
    client_curl.setopt(pycurl.URL, "https://www.arolla.fr/blog/author/edouard-gomez-vaez/")              #set url
    client_curl.setopt(pycurl.FOLLOWLOCATION, 1)
    client_curl.setopt(pycurl.WRITEFUNCTION, lambda x: None)
    content = client_curl.perform()
    dns_time = client_curl.getinfo(pycurl.NAMELOOKUP_TIME) #DNS time
    conn_time = client_curl.getinfo(pycurl.CONNECT_TIME)   #TCP/IP 3-way handshaking time
    starttransfer_time = client_curl.getinfo(pycurl.STARTTRANSFER_TIME)  #time-to-first-byte time
    total_time = client_curl.getinfo(pycurl.TOTAL_TIME)  #last requst time
    client_curl.close()

    data = json.dumps({'dns_time':dns_time,
                       'conn_time':conn_time,
                       'starttransfer_time':starttransfer_time,
                       'total_time':total_time,
    })

    return {
        'statusCode': 200,
        'body': data
    }
我有以下错误,这是可以理解的:

    Unable to import module 'lambda_function': No module named 'pycurl'
为了创建一个图层,我跟随了图图,但在使用docker生成图层时出现了以下错误(我提取了有趣的部分):

我甚至尝试在自己的机器上生成刚启动的层:

     pip install -r requirements.txt -t python/lib/python3.6/site-packages/
     zip -r mypythonlibs.zip python > /dev/null
然后在aws中将zip作为一个层上传,但在lanching lambda时,我出现了另一个错误:

    Unable to import module 'lambda_function': libssl.so.1.0.0: cannot open shared object file: No such file or directory

似乎该层必须建立在某种程度上扩展的目标环境上。

经过几个小时的努力,我终于解决了这个问题

TL;DR:使用继承自aws one的docker映像构建层,但使用所需的库,例如
libcurl-devel
openssl-devel
python36-devel
。看一看技巧笔记3:)

具体方式:

  • 先决条件:安装Docker
  • 在一个空目录中,复制包含
    pycurl
    requirements.txt
    (在我的例子中:
    pycurl~=7.43.0.5
  • 在同一目录中,创建以下
    Dockerfile
    (参见注释3):
  • 构建docker映像:
  • 通过运行以下命令,使用此图像构建层(参见注释2):
  • 通过运行以下命令压缩层:
  • 将文件
    mylayer.zip
    作为一个层发送到aws,并使您的lambda指向它(使用控制台或跟随tuto)

  • 测试你的lambda并庆祝

  • 注1。如果您想使用Python3.8,只需将3.6或36修改为3.8和38即可

    附注2。在重新生成层时,不要忘记删除python文件夹,必要时使用管理员权限

    附注3。注意DockerFile最后一行的符号链接。没有它,
    gcc
    将无法找到一些头文件,例如
    Python.h


    附注4。使用
    openssl
    后端编译
    pycurl
    ,因为它是lambda执行环境中使用的ssl后端。否则,在执行lambda时会出现
    libcurl链接时ssl后端(openssl)与编译时ssl后端不同的错误。

    为什么不直接使用
    urllib
    。这不需要任何层或依赖项,因为它是Pythons标准库的一部分。即使您不想使用
    urllib
    ,也可以使用
    请求
    ,这可能是比Lambda中的
    curl
    更好的选择。谢谢您,@Jens,这可能是一个解决办法。然而,在我的理解中,只有
    pycurl
    能够给出诸如TTLB、TTFB和DNS查找时间之类的度量。从您提供的代码中不清楚这一点。在这种情况下,
    urllib
    请求
    可能没有帮助。您是对的,我更改了代码以使其显式。
        Unable to import module 'lambda_function': libssl.so.1.0.0: cannot open shared object file: No such file or directory
    
    FROM public.ecr.aws/sam/build-python3.6
    
    RUN yum install libcurl-devel python36-devel -y
    
    RUN yum install openssl-devel -y
    ENV PYCURL_SSL_LIBRARY=openssl
    
    RUN ln -s /usr/include /var/lang/include
    
    docker build -t build-python3.6-pycurl .
    
    docker run -v "$PWD":/var/task "build-python3.6-pycurl" /bin/sh -c "pip install -r requirements.txt -t python/lib/python3.6/site-packages/; exit"
    
    zip mylayer.zip python > /dev/null