如何使用SAM在本地运行C ++ AWS Lambda函数?

时间:2019-10-18 13:21:45

标签: c++ amazon-web-services aws-lambda runtime serverless-application-model

我想尝试AWS Lambda的自定义C ++运行时,并使用SAM在本地对其进行测试。不幸的是,我收到错误Runtime exited without providing a reason(请比较下面的错误详细信息)。 如何使用SAM在本地运行C ++ Lambda函数?

方法:

我正在遵循official C++ Introduction blog中描述的确切步骤,直到“创建C ++函数”的最后一步。博客的其余部分是关于在Lambda上部署功能的(我不想这样做,因为我想在本地使用SAM)。

为了使用SAM,我将template.yaml放在构建目录中。 build dir的结构现在看起来像这样:

├── CMakeCache.txt
├── CMakeFiles
|   |...
├── cmake_install.cmake
├── hello
├── hello.zip
├── Makefile
└── template.yaml

6 directories, 37 files

这是构建目录中template.yaml的内容:

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
  cpp hello world

Globals: # default settings across all resources if nothing else is specified
  Function:
    Timeout: 15

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello.zip # relative location or S3 key
      Handler: hello # function to handle call? Why is this hello and not main?
      Runtime: provided
      Events:
        HelloWorld: # the name of the event
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get

Outputs:
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

调用:

我正在sam local start-api --debug文件夹中运行debug。 我通过在Chrome浏览器中转到127.0.0.1:3000/hello来调用该函数。

错误:

调用URL所产生的消息中的一些详细信息:

...
Invoking hello (provided)
Decompressing /home/path/to/folder/test_cpp_local/aws-lambda-cpp/build/hello_cpp/build/hello.zip

Fetching lambci/lambda:provided Docker container image......
Mounting /tmp/tmpm9djt4mb as /var/task:ro,delegated inside runtime container
/var/task/bin/hello: error while loading shared libraries: /var/task/lib/libc.so.6: file too short
START RequestId: 3435a342-d86d-1a59-df1a-10167070cd22 Version: $LATEST
END RequestId: 3435a342-d86d-1a59-df1a-10167070cd22
REPORT RequestId: 3435a342-d86d-1a59-df1a-10167070cd22  Init Duration: 29.71 ms Duration: 0.00 ms   Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 6 MB   
{
  "errorType": "Runtime.ExitError",
  "errorMessage": "RequestId: 3435a342-d86d-1a59-df1a-10167070cd22 Error: Runtime exited without providing a reason"
}
Function returned an invalid response (must include one of: body, headers, multiValueHeaders or statusCode in the response object
...

我的系统:

我正在使用cmake 3.5.1,g ++ 4.5.0,gcc 4.5.0在Ubuntu 16.04上构建

想法如何解决此问题:

我必须以某种方式在使用AWS Linux的计算机上进行远程构建(我希望情况并非如此)

我可以按照此处CloudFormationPackage的建议使用stackoverflow。我想避免这种情况,因为我只想在本地进行测试。

2 个答案:

答案 0 :(得分:1)

问题可能在这里: /var/task/bin/hello: error while loading shared libraries: /var/task/lib/libc.so.6: file too short

您的二进制文件甚至不会调用。

您应该能够通过在匹配版本AWS Linux上构建二进制文件或通过构建静态二进制文件来解决此问题。

答案 1 :(得分:0)

在docker容器中运行

我认为这是SAM的问题。我能够使用docker-lambda来构建它。为此,我必须提取hello.zip,然后用

进行调用
docker run --rm -v "<path/to/hello>":/var/task lambci/lambda:provided handler

使用此替代方法,我不需要静态构建。

在Docker容器中构建

您也可以在amazonlinux容器中构建。 hello_world Dockerfile如下所示(包括程序本身):

FROM amazonlinux:latest

RUN yum -y install make 
RUN yum -y install git 
RUN yum -y install gcc-c++
RUN yum -y install nano 
RUN yum -y install zip 
RUN yum -y install clang 
RUN yum -y install gcc-c++
RUN yum -y install libcurl-devel 
RUN yum -y install cmake3
RUN export CC=gcc && \
    export CXX=g++ && \
    cd ~  && \
    git clone https://github.com/awslabs/aws-lambda-cpp.git && \
    cd aws-lambda-cpp && \
    mkdir build && \
    cd build && \
    cmake3 .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=~/out && \
    make &&\
    make install && \
    mkdir hello-cpp-world && \
    cd hello-cpp-world && \
    echo -e "// main.cpp\n#include <aws/lambda-runtime/runtime.h>\nusing namespace aws::lambda_runtime;\ninvocation_response my_handler(invocation_request const& request)\n{\n   return invocation_response::success(\"Hello, World!\", \"application/json\");\n}\n\nint main()\n{\nrun_handler(my_handler);\n   return 0; \n}" >> main.cpp && \
    echo -e "cmake_minimum_required(VERSION 3.5)\nset(CMAKE_CXX_STANDARD 11)\nproject(hello LANGUAGES CXX)\nfind_package(aws-lambda-runtime REQUIRED)\nadd_executable(hello \"main.cpp\")\ntarget_link_libraries(hello PUBLIC AWS::aws-lambda-runtime)\naws_lambda_package_target(hello NO_LIBC)" >> CMakeLists.txt && \
    mkdir build &&\
    cd build &&\
    cmake3 .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=~/out && \
    make && \
    make aws-lambda-package-hello
RUN cd / && \
    cp /root/aws-lambda-cpp/build/hello-cpp-world/build/hello.zip /artifacts/hello.zip

重要的是,如果要在amazonlinux环境中进行构建,则必须在aws_lambda_package_target(hello NO_LIBC)中包含CMakeLists.txt。这是为了不将C运行时作为依赖项包括在内。

在此示例中,我在容器内安装了一个名为artifacts的文件夹,并将生成的zip文件复制到该文件夹​​中。