为什么无服务器计算不是炒作,而是拯救你钱包和神经的良方
\n\n想象一下:你用C#编写了一个很棒的API,将其部署在虚拟机上,但它每天有23小时处于闲置状态。你是在为空气付费。熟悉吗?如果是这样,那么C#无服务器函数就是你的救生圈。无服务器计算(或函数即服务)允许你仅在真正需要时执行代码。无需租用服务器,无需手动配置基础设施的CI/CD,无需为扩展而头疼。
\n\n在本文中,我们将探讨如何为AWS Lambda和Azure Functions编写C#无服务器函数,进行比较,编写实际代码,并理解为什么这是微服务、事件处理器和移动应用后端的最佳选择。是的,这里会有很多代码——绝不掺水。
\n\nAWS Lambda与C#:如何让两个强大工具协同工作
\n\nAWS Lambda C# 可能是使用Amazon Web Services的.NET开发人员最流行的选择。Lambda支持.NET Core 3.1、.NET 6、.NET 8甚至.NET 9(请在阅读时确认最新版本)。主要优势在于,你使用熟悉的C#编写代码,而AWS自行处理运行时环境。
\n\n创建你的第一个C# Lambda函数
\n\n首先,安装适用于Visual Studio的AWS Toolkit,或使用.NET CLI。我们将使用“AWS Lambda Project”模板创建一个项目。
\n\ndotnet new lambda.EmptyFunction --name HelloWorldFunction\ncd HelloWorldFunction\ndotnet add package Amazon.Lambda.Core\ndotnet add package Amazon.Lambda.Serialization.SystemTextJson\n\n现在,让我们编写函数本身。一个经典示例是处理API Gateway请求并返回JSON。
\n\nusing Amazon.Lambda.Core;\nusing Amazon.Lambda.Serialization.SystemTextJson;\n\n[assembly: LambdaSerializer(typeof(DefaultLambdaJsonSerializer))]\n\npublic class Function\n{\n public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest input, ILambdaContext context)\n {\n var message = $"你好,世界!你的请求:{input.Body ?? "空"}";\n context.Logger.LogInformation("Lambda函数已被调用");\n\n return new APIGatewayProxyResponse\n {\n StatusCode = 200,\n Body = JsonSerializer.Serialize(new { message, timestamp = DateTime.UtcNow }),\n Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }\n };\n }\n}\n\n请注意:代码是异步的,使用了内置的JSON序列化和日志记录。这是一个最小可行产品,已经可以在负载下运行。
\n\n为什么AWS Lambda在C#方面胜出?
\n- \n
- 冷启动: AWS通过SnapStart优化了.NET函数的启动——现在启动时间不到200毫秒。 \n
- 集成: 开箱即用地支持S3、DynamoDB、SQS、API Gateway。 \n
- 监控: CloudWatch收集日志、指标和错误。 \n
适用于C#的Azure Functions:来自微软的可靠替代方案
\n\n如果你的项目已经依赖于微软生态系统(Azure DevOps、Active Directory、SQL Server),那么Azure Functions C#可能更方便。它们不仅支持独立进程(isolated process),还支持进程内模型。
\n\n适用于Azure的C#函数示例
\n\n让我们使用Azure Functions Core Tools创建一个HTTP触发器:
\n\nfunc init MyFunctionApp --dotnet-isolated\ncd MyFunctionApp\nfunc new --name HttpExample --template "HTTP trigger"\n\n函数代码:
\n\nusing Microsoft.Azure.Functions.Worker;\nusing Microsoft.Extensions.Logging;\n\npublic class HttpExample\n{\n private readonly ILogger<HttpExample> _logger;\n\n public HttpExample(ILogger<HttpExample> logger)\n {\n _logger