如何使用 SAM 在本地 运行 C++ AWS Lambda 函数?
How to run a C++ AWS Lambda Function locally with SAM?
我想尝试 AWS Lambda 的自定义 C++ 运行time 并使用 SAM 在本地进行测试。不幸的是,我收到错误 Runtime exited without providing a reason
(比较下面的错误详细信息)。 我如何 运行 C++ Lambda 在本地使用 SAM 函数?
方法:
我正在按照 official C++ Introduction blog 中描述的确切步骤进行操作,直到 "Create your C++ function" 的最后一步。博客的其余部分是关于在 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 as recommended here Whosebug。我想避免这种情况,因为我只想在本地进行测试。
问题可能出在这里:
/var/task/bin/hello: error while loading shared libraries: /var/task/lib/libc.so.6: file too short
您的二进制文件甚至没有调用。
您应该能够通过在 AWS Linux
的匹配版本上构建二进制文件或构建静态二进制文件来解决此问题。
运行 在 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 文件复制到该文件夹中。
我想尝试 AWS Lambda 的自定义 C++ 运行time 并使用 SAM 在本地进行测试。不幸的是,我收到错误 Runtime exited without providing a reason
(比较下面的错误详细信息)。 我如何 运行 C++ Lambda 在本地使用 SAM 函数?
方法:
我正在按照 official C++ Introduction blog 中描述的确切步骤进行操作,直到 "Create your C++ function" 的最后一步。博客的其余部分是关于在 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 as recommended here Whosebug。我想避免这种情况,因为我只想在本地进行测试。
问题可能出在这里:
/var/task/bin/hello: error while loading shared libraries: /var/task/lib/libc.so.6: file too short
您的二进制文件甚至没有调用。
您应该能够通过在 AWS Linux
的匹配版本上构建二进制文件或构建静态二进制文件来解决此问题。
运行 在 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 文件复制到该文件夹中。