【问题标题】:Calling AWS Lambda Function in C#在 C# 中调用 AWS Lambda 函数
【发布时间】:2018-08-04 14:29:37
【问题描述】:

我正在尝试从控制台应用程序运行 Lambda 函数。这个想法是让它快速运行并忘记 lambda 函数,而无需等待 lambda 函数返回。我的代码似乎根本没有执行 lambda 函数。我知道该功能有效,因为我可以运行测试。当我运行下面的代码时,我只是得到一个任务取消异常。

var jsonSerializer = new JsonSerializer();
var lambdaConfig = new AmazonLambdaConfig() { RegionEndpoint = RegionEndpoint.USEast2 };
var lambdaClient = new AmazonLambdaClient(lambdaConfig);

using (var memoryStream = new MemoryStream())
{
    jsonSerializer.Serialize(myData, memoryStream);
    var lambdaRequest = new InvokeRequest
    {
        FunctionName = "MyFunction",
        InvocationType = "Event",
        PayloadStream = memoryStream
};

var result = Task.Run(async () => { return await lambdaClient.InvokeAsync(lambdaRequest); }).Result;

有人知道我做错了什么吗?

谢谢!

【问题讨论】:

    标签: c# amazon-web-services aws-lambda fire-and-forget


    【解决方案1】:

    如果数据是带双引号的有效 JSON,您可以直接传递您的 myData,而不是转换为 MemoryStream。

    在函数名称中,您可以使用 ARN 或仅使用名称。在最新版本 AWSSDK.Lambda -Version 3.3.103.31

    中,两者都适用于我
    static readonly string awsAccessKey = "access key here";
    static readonly string awsSecretKey = "secret key here";
    
    private static BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
    private static AmazonLambdaConfig lambdaConfig = new AmazonLambdaConfig() { RegionEndpoint = RegionEndpoint.USEast1 };
    private static AmazonLambdaClient lambdaClient = new AmazonLambdaClient(awsCredentials, lambdaConfig);
    
    public async Task<string> GetLambdaResponse(string myData)
    {
        var lambdaRequest = new InvokeRequest
        {
            FunctionName = "mylambdafunction",
            Payload = myData
        };
    
        var response = await lambdaClient.InvokeAsync(lambdaRequest);
        if (response != null)
        {
            using (var sr = new StreamReader(response.Payload))
            {
                return await sr.ReadToEndAsync();
            }
        }
        return string.Empty;        
    }
    

    【讨论】:

      【解决方案2】:

      混合阻塞调用可能会导致死锁。如果意图是触发和获取,那么只需调用所需的函数。还有为什么要给请求一个流,只是在病房后处理它

      public static void Main(string[] args) {    
          var jsonSerializer = new JsonSerializer();
          var lambdaConfig = new AmazonLambdaConfig() { RegionEndpoint = RegionEndpoint.USEast2 };
          var lambdaClient = new AmazonLambdaClient(lambdaConfig);
      
          var memoryStream = new MemoryStream();
      
          jsonSerializer.Serialize(myData, memoryStream);
          var lambdaRequest = new InvokeRequest
          {
              FunctionName = "MyFunction",
              InvocationType = "Event",
              PayloadStream = memoryStream
          };
      
          lambdaClient.InvokeAsync(lambdaRequest);
      
          Console.ReadLine();
      }
      

      【讨论】:

      • 你提出的代码是我开始的,不幸的是 lambda 函数从未被调用,程序完成但该函数从未被触发。我开始将它包装在 Task.Run 中,只是为了看看它是否会返回正面或负面的响应。
      • 嗨科里,你有没有让这个工作?我也有同样的问题。
      【解决方案3】:

      我认为您的代码中有两个问题:

      • (由@Nikosi 提及)您在将 memoryStream 用于 lambda 调用之前对其进行处置
      • (对我的情况有帮助的修复程序)当您将有效负载序列化到内存流中时,流中的位置指向其结束后的字节,因此 SDK 无法从中读取任何内容。所以我只用了memoryStream.Seek(0L, SeekOrigin.Begin)

      顺便说一句,假设JsonSerializer 是Newtonsoft.Json 包中的那个,我没有找到接受Stream 参数的Serialize 方法,只有TextWriterJsonWriter。因此,可能有必要将其包装到 StreamWriter 并确保调用 FlushFlushAsync(或在使用内存流作为 Lambda 有效负载之前处置 StreamWriter),如下所示:

      await using var stream = new MemoryStream();
      await using var streamWriter = new StreamWriter(stream);
      var serializer = new JsonSerializer();
      serializer.Serialize(streamWriter, payload);
      await streamWriter.FlushAsync();
      stream.Seek(0L, SeekOrigin.Begin);
      
      log.LogInformation("Batch {0}: sending {1} messages to Lambda", batchId, batch.Count);
      
      var lambdaResponse = await lambda.InvokeAsync(new InvokeRequest
      {
          InvocationType = InvocationType.RequestResponse,
          PayloadStream = stream,
          //Payload = JsonConvert.SerializeObject(payload),
          FunctionName = lambdaArn
      }, stoppingToken);
      

      【讨论】:

        【解决方案4】:

        Nkosi 的答案中的 FunctionName 实际上应该是您的 lambda 函数的整个 ARN,因此请参考 Nkosi 的答案:

        public static void Main(string[] args) {    
        var jsonSerializer = new JsonSerializer();
        var lambdaConfig = new AmazonLambdaConfig() { RegionEndpoint = RegionEndpoint.USEast2 };
        var lambdaClient = new AmazonLambdaClient(lambdaConfig);
        
        var memoryStream = new MemoryStream();
        
        jsonSerializer.Serialize(myData, memoryStream);
        var lambdaRequest = new InvokeRequest
        {
            FunctionName = "arn:aws:lambda:ap-southeast-2:{id}:function:MyFunction",
            InvocationType = "Event",
            PayloadStream = memoryStream
        };
        
        lambdaClient.InvokeAsync(lambdaRequest);
        
        Console.ReadLine();
        

        【讨论】:

        • 我将不得不试一试,我最终放弃了它,转而支持我编写的 azure 函数。我想看看我是否可以让它变得多余。谢谢!
        猜你喜欢
        • 2018-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-22
        相关资源
        最近更新 更多