是否可以使用无服务器框架将.Net Core 3服务部署到AWS Lambda?

时间:2019-10-01 15:41:15

标签: amazon-web-services .net-core aws-lambda serverless-framework

现在,.Net Core 3已删除,AWS宣布了自定义运行时,我希望利用某些新的.Net Core 3功能。不幸的是,在尝试查找有关如何使用无服务器框架执行此操作的信息时,我将简短介绍。外面有没有人这样做?如果是这样,是否有一个很好的在线资源来提供帮助?

1 个答案:

答案 0 :(得分:1)

简短的回答是“是”。

亚马逊州:

  

Lambda团队的政策是支持运行时的长期支持(LTS)版本,因此AWS Lambda本身不支持.NET Core 3.0。

     

但这并不意味着您今天不能在Lambda上使用.NET Core 3.0。借助Amazon.Lambda.RuntimeSupport NuGet包,您可以使用任何版本的.NET Core,包括3.0。这是可能的,因为.NET Core的一大功能是能够将应用程序打包为完全独立的部署捆绑包。以下博客文章显示了如何使用Amazon.Lambda.RuntimeSupport。 https://aws.amazon.com/blogs/developer/announcing-amazon-lambda-runtimesupport/

我们已将.Net Core 3.0 Web Api成功部署到AWS Serverless。

这是我的做法:

  1. 添加了NuGet软件包:
 Amazon.Lambda.AspNetCoreServer 
 Amazon.Lambda.RuntimeSupport
  1. 添加了Lambda入口点
    public class LambdaEntryPoint :
        // When using an ELB's Application Load Balancer as the event source change 
        // the base class to Amazon.Lambda.AspNetCoreServer.ApplicationLoadBalancerFunction
        Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction
    {
        /// <summary>
        /// The builder has configuration, logging and Amazon API Gateway already configured. The startup class
        /// needs to be configured in this method using the UseStartup<>() method.
        /// </summary>
        /// <param name="builder"></param>
        protected override void Init(IWebHostBuilder builder)
        {
            builder.UseStartup<Startup>();
        }
    }
  1. 更新后的主要功能
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Amazon.Lambda.Core;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.RuntimeSupport;
using Amazon.Lambda.Serialization.Json;

namespace CustomRuntimeAspNetCore30
{
    public class Program
    {

        public static void Main(string[] args)
        {
            if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("AWS_LAMBDA_FUNCTION_NAME")))
            {
                CreateHostBuilder(args).Build().Run();
            }
            else
            {
                var lambdaEntry = new LambdaEntryPoint();
                var functionHandler = (Func<APIGatewayProxyRequest, ILambdaContext, Task<APIGatewayProxyResponse>>)(lambdaEntry.FunctionHandlerAsync);
                using (var handlerWrapper = HandlerWrapper.GetHandlerWrapper(functionHandler, new JsonSerializer()))
                using (var bootstrap = new LambdaBootstrap(handlerWrapper))
                {
                    bootstrap.RunAsync().Wait();
                }
            }
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}
  1. 添加了serverless.template文件:
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Transform": "AWS::Serverless-2016-10-31",
  "Description": "An AWS Serverless Application that uses the ASP.NET Core framework running in Amazon Lambda.",
  "Parameters": {},
  "Conditions": {},
  "Resources": {
    "AspNetCoreFunction": {
      "Type": "AWS::Serverless::Function",
      "Properties": {
        "Handler": "not-required",
        "Runtime": "provided",
        "CodeUri": "",
        "MemorySize": 256,
        "Timeout": 30,
        "Role": null,
        "Policies": [
          "AWSLambdaFullAccess"
        ],
        "Environment": {
          "Variables": {
            "LAMBDA_NET_SERIALIZER_DEBUG": "true"
          }
        },
        "Events": {
          "ProxyResource": {
            "Type": "Api",
            "Properties": {
              "Path": "/{proxy+}",
              "Method": "ANY"
            }
          },
          "RootResource": {
            "Type": "Api",
            "Properties": {
              "Path": "/",
              "Method": "ANY"
            }
          }
        }
      }
    }
  },
  "Outputs": {
    "ApiURL": {
      "Description": "API endpoint URL for Prod environment",
      "Value": {
        "Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
      }
    }
  }
}
  1. 添加了aws-lambda-tools-defaults.json
{
  "Information": [
    "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
    "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
    "dotnet lambda help",
    "All the command line options for the Lambda command can be specified in this file."
  ],
  "profile": "default",
  "region": "",
  "configuration": "Release",
  "s3-prefix": "CustomRuntimeAspNetCore30/",
  "template": "serverless.template",
  "template-parameters": "",
  "msbuild-parameters": "--self-contained true /p:AssemblyName=bootstrap",
  "framework": "netcoreapp3.0",
  "s3-bucket": "",
  "stack-name": "CustomRuntimeAspNetCore30"
}
  1. 打开Visual Studio部署向导。

编辑项目文件,以在PropertyGroup集合中包含值为Lambda的AWSProjectType。

<PropertyGroup>
  <TargetFramework>netcoreapp3.0</TargetFramework>
  <AWSProjectType>Lambda</AWSProjectType>
</PropertyGroup>

然后您可以通过在Visual Studio中右键单击该项目并选择“发布到AWS Lambda ...”来将ASP.NET Core项目部署到Lambda。

更多信息在这里:

https://aws.amazon.com/blogs/developer/net-core-3-0-on-lambda-with-aws-lambdas-custom-runtime/

请注意,如果您要发布的webapi项目引用了其他程序集,则此过程可能会出错。这是因为在部署(步骤5)中,它尝试将所有程序集重命名为“ bootstrap”。那么您将需要:

将csproj文件中项目的程序集名称重命名为'bootstrap'(不带引号)。 修改aws-lambda-tools-defaults.json,使该行:

"msbuild-parameters": "--self-contained true /p:AssemblyName=bootstrap",

成为

"msbuild-parameters"  : "--self-contained true",

还请注意,日志记录似乎已从.Net 2.1更改。

我尝试根据.Net Core 2.1实现日志记录。那就是:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
       Host.CreateDefaultBuilder(args)
         .ConfigureLogging(logging =>
         {
            logging.AddAWSProvider();
            logging.SetMinimumLevel(LogLevel.Debug);
         })
         .ConfigureWebHostDefaults(webBuilder =>
         {
            webBuilder.UseStartup<startup>();
         });

(以及LambdaEntryPoint.cs中的类似代码)

但是,这不起作用。查看代码,它正在尝试查找IConfiguration ImplementationInstance,它为null。

根据此https://github.com/aspnet/AspNetCore/issues/14400,此重大更改是设计使然。

要使日志在.Net Core 3中正常工作,您需要向Startup.Configure()添加代码:

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
        {
            var loggingConfigSection = Configuration.GetAWSLoggingConfigSection();
            var awsLoggerProvider = new AWSLoggerProvider(loggingConfigSection);
            loggerFactory.AddProvider(awsLoggerProvider);

            // rest of code
        }