为什么在无服务器世界中使用C++?
\n\n当听到“无服务器”时,首先想到的通常是JavaScript、Python或Go。但如果我告诉你,可以在AWS Lambda、Google Cloud Functions甚至自定义运行时中运行C++呢?这不仅仅是一个技巧,对于每一毫秒都至关重要的任务来说,这是一个非常有意义的方案。
\n\n在无服务器中使用C++,关乎速度和冷启动。当Python函数还在加载解释器和依赖项时,C++可能已经执行完毕。但有一些注意事项:你需要为Linux编译二进制文件,将其打包成ZIP文件,并指定自定义运行时。听起来很复杂?实际上并非如此。让我们来一探究竟。
\n\n无服务器如何支持C++?
\n\n关键在于,云提供商默认不支持编译型语言。例如,AWS Lambda官方仅支持Python、Node.js、Java、Go、.NET和Ruby。但Lambda有一个自定义运行时机制——你可以提供任何二进制文件,通过HTTP与Lambda运行时API通信。
\n\n流程很简单:
\n- \n
- 你在Amazon Linux 2(或兼容环境)下编译C++代码。 \n
- 将可执行文件与
bootstrap脚本(或直接重命名为bootstrap的二进制文件)一起打包。 \n - 将ZIP文件上传到Lambda,并选择“提供您自己的bootstrap”。 \n
同样,你也可以在Google Cloud Functions(通过Cloud Run或Knative)和Azure Functions(通过Docker镜像)中实现。
\n\n构建一个简单的C++ Lambda函数
\n\n让我们编写一个函数,它接收包含两个数字的JSON并返回它们的和。这是经典示例,但用C++实现。
\n\n// main.cpp\n#include <iostream>\n#include <string>\n#include <nlohmann/json.hpp>\n\nusing json = nlohmann::json;\n\nint main() {\n // 从stdin读取事件(Lambda通过这种方式传递)\n std::string input;\n std::getline(std::cin, input);\n\n auto event = json::parse(input);\n\n int a = event["a"];\n int b = event["b"];\n int sum = a + b;\n\n json result;\n result["statusCode"] = 200;\n result["body"] = std::to_string(sum);\n\n // 输出到stdout——这是Lambda的响应\n std::cout << result.dump() << std::endl;\n\n return 0;\n}\n\n\n编译时,我们需要g++编译器和nlohmann/json库(下载头文件)。为了不携带.so文件,我们进行静态编译:
g++ -std=c++17 -static -O2 main.cpp -o bootstrap\n\n\n现在创建一个只包含bootstrap文件的ZIP压缩包,并上传到Lambda。完成!函数已就绪。
错误处理与日志记录
\n\n在实际项目中,需要正确处理JSON解析错误并返回清晰的响应。AWS Lambda期望你的二进制文件在成功时以0退出,在出错时以非零退出。日志可以写入stderr——它们会出现在CloudWatch中。
if (!event.contains("a") || !event.contains("b")) {\n std::cerr << "Missing parameters" << std::endl;\n json error;\n error["statusCode"] = 400;\n error["body"] = "Bad Request";\n std::cout << error.dump() << std::endl;\n return 1;\n}\n\n\nC++的AWS Lambda替代方案
\n\n不想折腾自定义运行时?还有其他选择。
\n\nGoogle Cloud Run + Knative
\n\n你可以将C++应用程序打包成Docker镜像并在Cloud Run上运行。这并非严格意义上的“函数”,而是容器化无服务器,但对于C++来说是最简单的途径。冷启动时间会更长(几秒),但没有运行时限制。
\n\n带Docker的Azure Functions
\n\n类似地——使用Docker和任何包含C++运行时的镜像。Azure通过custom handlers支持自定义处理器。