

 适用于 .NET 的 Amazon SDK V3 已进入维护模式。

我们建议您迁移到 [适用于 .NET 的 Amazon SDK V4](https://docs.amazonaws.cn/sdk-for-net/v4/developer-guide/welcome.html)。有关如何迁移的更多详细信息和信息，请参阅我们的[维护模式公告](https://www.amazonaws.cn/blogs/developer/aws-sdk-for-net-v3-maintenance-mode-announcement/)。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 适用于 .NET 的 Amazon SDK 的高级库和框架
<a name="high-level-libraries"></a>

以下各节包含有关不属于 SDK 核心功能的高级库和框架的信息。这些库和框架使用核心 SDK 功能来创建可简化某些任务的功能。

如果您不熟悉适用于 .NET 的 Amazon SDK，则可能需要先查看[快速了解](quick-start.md)主题。其中提供了对软件开发工具包的简单介绍。

开始之前，请确保您已[完成环境和项目的设置](net-dg-config.md)。还要查看[软件开发工具包功能](net-dg-sdk-features.md)中的信息。

**Topics**
+ [Message Processing Framework](msg-proc-fw.md)
+ [将 Amazon 与 .NET Aspire 集成](aspire-integrations.md)

# Amazon Message Processing Framework for .NET
<a name="msg-proc-fw"></a>

Amazon Message Processing Framework for .NET 是一个 Amazon 原生框架，它简化了使用 Amazon Simple Queue Service (SQS)、Amazon Simple Notification Service (SNS)、Amazon EventBridge 等 Amazon 服务的 .NET 消息处理应用程序的开发。该框架减少了开发人员需要编写的样板代码量，使您能够在发布和使用消息时专注于业务逻辑。有关该框架如何简化开发的详细信息，请参阅博客文章 [Introducing the Amazon Message Processing Framework for .NET (Preview)](https://www.amazonaws.cn/blogs/developer/introducing-the-aws-message-processing-framework-for-net-preview/)。第一部分特别提供了演示，展示了使用低级别 API 调用和使用框架之间的区别。

Message Processing Framework 支持以下活动和功能：
+ 向 SQS 发送消息，向 SNS 和 EventBridge 发布事件。
+ 使用长时间运行的轮询器接收和处理来自 SQS 的消息，这种方式通常用于后台服务。这包括在处理消息时管理可见性超时，以防止其他客户端处理该消息。
+ 在 Amazon Lambda 函数中处理消息。
+ FIFO（先进先出）SQS 队列和 SNS 主题。
+ 用于记录的 OpenTelemetry。

有关这些活动和功能的详细信息，请参阅[博客文章](https://www.amazonaws.cn/blogs/developer/introducing-the-aws-message-processing-framework-for-net-preview/)的 **功能** 部分以及下列主题。

开始之前，请确保您已[完成环境和项目的设置](net-dg-config.md)。还要查看[软件开发工具包功能](net-dg-sdk-features.md)中的信息。

**其他资源**
+ [NuGet.org](https://www.nuget.org/) 上的 [https://www.nuget.org/packages/AWS.Messaging/](https://www.nuget.org/packages/AWS.Messaging/) 软件包。
+ [API 参考](https://aws.github.io/aws-dotnet-messaging/)。
+ GitHub 存储库中的`README`文件，网址为 [https://github.com/aws/aws-dotnet-messaging/](https://github.com/aws/aws-dotnet-messaging/)
+ Microsoft 的 [.NET 依赖项注入](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection)。
+ Microsoft 的 [.NET 通用主机](https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host)。

**Topics**
+ [开始使用](msg-proc-fw-get-started.md)
+ [发布消息](msg-proc-fw-publish.md)
+ [使用消息](msg-proc-fw-consume.md)
+ [FIFO](msg-proc-fw-fifo.md)
+ [日志记录和 OpenTelemetry](msg-proc-fw-telemetry.md)
+ [自定义](msg-proc-fw-customize.md)
+ [安全性](msg-proc-fw-security.md)

# 开始使用 Amazon Message Processing Framework for .NET
<a name="msg-proc-fw-get-started"></a>

开始之前，请确保您已[完成环境和项目的设置](net-dg-config.md)。还要查看[软件开发工具包功能](net-dg-sdk-features.md)中的信息。

本主题介绍如何开始使用 Message Processing Framework。除了先决条件和配置信息外，本主题还提供相关教程来展示如何实现常见场景。

## 先决条件和配置
<a name="mpf-get-started-prereq"></a>
+ 您为应用程序提供的凭证必须具备消息服务及其所用操作的相应权限。有关更多信息，请参阅 [SQS](https://docs.amazonaws.cn/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-authentication-and-access-control.html)、[SNS](https://docs.amazonaws.cn/sns/latest/dg/security-iam.html) 和 [EventBridge](https://docs.amazonaws.cn/eventbridge/latest/userguide/eb-iam.html) 各自开发人员指南中的安全性主题。另请参阅 GitHub 上[自述文件](https://github.com/aws/aws-dotnet-messaging/)中关于特定[权限](https://github.com/aws/aws-dotnet-messaging/blob/main/README.md#permissions)的部分。
+ 要使用 Amazon Message Processing Framework for .NET，您必须将 [https://www.nuget.org/packages/AWS.Messaging](https://www.nuget.org/packages/AWS.Messaging) NuGet 软件包添加到您的项目中。例如：

  ```
  dotnet add package AWS.Messaging
  ```
+ 该框架与 .NET 的[依赖项注入（DI）服务容器](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection)集成。您可以在应用程序启动过程中通过调用 `AddAWSMessageBus` 将其添加到 DI 容器来配置框架。

  ```
  var builder = WebApplication.CreateBuilder(args);
  
  // Register the AWS Message Processing Framework for .NET
  builder.Services.AddAWSMessageBus(builder =>
  {
      // Register that you'll publish messages of type ChatMessage to an existing queue
      builder.AddSQSPublisher<ChatMessage>("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd");
  });
  ```

## 教程
<a name="mpf-get-started-tutorial"></a>

本教程演示了如何使用 Amazon Message Processing Framework for .NET。它创建了两个应用程序：一个 ASP.NET Core Minimal API，用于在 API 端点收到请求时向 Amazon SQS 队列发送消息；一个长时间运行的控制台应用程序，用于轮询和处理这些消息。
+ 本教程中的说明偏好使用 .NET CLI，但您既可以使用 .NET CLI 等跨平台工具，也可以使用 Microsoft Visual Studio 来完成本教程。有关这些工具的信息，请参阅[安装和配置工具链](net-dg-dev-env.md)。
+ 本教程假定您使用 `[default]` 配置文件作为凭证。它还假定短期凭证具有发送和接收 Amazon SQS 消息的相应权限。有关更多信息，请参阅[使用配置 SDK 身份验证 Amazon](creds-idc.md)和 [SQS](https://docs.amazonaws.cn/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-authentication-and-access-control.html) 的安全性主题。

**注意**  
运行本教程可能会产生 SQS 消息收发费用。

### 步骤
<a name="mpf-tutorial-steps"></a>
+ [创建 SQS 队列](#mpf-tutorial-queue)
+ [创建并运行发布应用程序](#mpf-tutorial-publish)
+ [创建并运行处理应用程序](#mpf-tutorial-handle)
+ [清理](#mpf-tutorial-cleanup)

### 创建 SQS 队列
<a name="mpf-tutorial-queue"></a>

本教程需要一个 SQS 队列来向其发送消息和从中接收消息。可以使用 Amazon CLI 或 Amazon Tools for PowerShell 的以下命令之一来创建队列。记下返回的队列 URL，以便可以在后续框架配置过程中指定它。

------
#### [ Amazon CLI ]

```
aws sqs create-queue --queue-name DemoQueue
```

------
#### [ Amazon Tools for PowerShell ]

```
New-SQSQueue -QueueName DemoQueue
```

------

### 创建并运行发布应用程序
<a name="mpf-tutorial-publish"></a>

按照以下程序创建并运行发布应用程序。

1. 打开命令提示符或终端。查找或创建可以在其中创建 .NET 项目的操作系统文件夹。

1. 在该文件夹中，运行以下命令以创建 .NET 项目。

   ```
   dotnet new webapi --name Publisher
   ```

1. 导航到新项目的文件夹。在 Amazon Message Processing Framework for .NET 上添加依赖项。

   ```
   cd Publisher
   dotnet add package AWS.Messaging
   ```
**注意**  
如果您使用 Amazon IAM Identity Center 进行身份验证，请务必同时添加 `AWSSDK.SSO` 和 `AWSSDK.SSOOIDC`。

1. 使用以下代码替换 `Program.cs` 中的代码。

   ```
   using AWS.Messaging;
   using Microsoft.AspNetCore.Mvc;
   using Publisher;
   
   var builder = WebApplication.CreateBuilder(args);
   
   // Add services to the container.
   // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle.
   builder.Services.AddEndpointsApiExplorer();
   builder.Services.AddSwaggerGen();
   
   
   // Configure the AWS Message Processing Framework for .NET.
   builder.Services.AddAWSMessageBus(builder =>
   {
       // Check for input SQS URL.
       // The SQS URL should be passed as a command line argument or set in the Debug launch profile.
       if ((args.Length == 1) && (args[0].Contains("https://sqs.")))
       {
           // Register that you'll publish messages of type GreetingMessage:
           // 1. To a specified queue.
           // 2. Using the message identifier "greetingMessage", which will be used
           //    by handlers to route the message to the appropriate handler.
           builder.AddSQSPublisher<GreetingMessage>(args[0], "greetingMessage");
       }
       // You can map additional message types to queues or topics here as well.
   });
   var app = builder.Build();
   
   
   // Configure the HTTP request pipeline.
   if (app.Environment.IsDevelopment())
   {
       app.UseSwagger();
       app.UseSwaggerUI();
   }
   
   app.UseHttpsRedirection();
   
   // Create an API Endpoint that receives GreetingMessage objects
   // from the caller and then sends them as an SQS message.
   app.MapPost("/greeting", async ([FromServices] IMessagePublisher publisher, Publisher.GreetingMessage message) =>
       {
           return await PostGreeting(message, publisher);
       })
   .WithName("SendGreeting")
   .WithOpenApi();
   
   app.Run();
   
   public partial class Program
   {
       /// <summary>
       /// Endpoint for posting a greeting message.
       /// </summary>
       /// <param name="greetingMessage">The greeting message.</param>
       /// <param name="messagePublisher">The message publisher.</param>
       /// <returns>Async task result.</returns>
       public static async Task<IResult> PostGreeting(GreetingMessage greetingMessage,
           IMessagePublisher messagePublisher)
       {
           if (greetingMessage.SenderName == null || greetingMessage.Greeting == null)
           {
               return Results.BadRequest();
           }
   
           // Publish the message to the queue configured above.
           await messagePublisher.PublishAsync(greetingMessage);
   
           return Results.Ok();
       }
   }
   
   namespace Publisher
   {
       /// <summary>
       /// This class represents the message contents.
       /// </summary>
       public class GreetingMessage
       {
           public string? SenderName { get; set; }
           public string? Greeting { get; set; }
       }
   }
   ```

1. 运行以下命令。这应该会打开一个带有 Swagger UI 的浏览器窗口，让您能够浏览和测试 API。

   ```
   dotnet watch run <queue URL created earlier>
   ```

1. 打开 `/greeting` 端点并选择**试用**。

1. 为消息指定 `senderName` 和 `greeting` 值，然后选择**执行**。这会调用您的 API，该 API 会发送 SQS 消息。

### 创建并运行处理应用程序
<a name="mpf-tutorial-handle"></a>

按照以下程序创建并运行处理应用程序。

1. 打开命令提示符或终端。查找或创建可以在其中创建 .NET 项目的操作系统文件夹。

1. 在该文件夹中，运行以下命令以创建 .NET 项目。

   ```
   dotnet new console --name Handler
   ```

1. 导航到新项目的文件夹。在 Amazon Message Processing Framework for .NET 上添加依赖项。还要添加 `Microsoft.Extensions.Hosting` 软件包，支持您通过 [.NET 通用主机](https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host)配置框架。

   ```
   cd Handler
   dotnet add package AWS.Messaging
   dotnet add package Microsoft.Extensions.Hosting
   ```
**注意**  
如果您使用 Amazon IAM Identity Center 进行身份验证，请务必同时添加 `AWSSDK.SSO` 和 `AWSSDK.SSOOIDC`。

1. 使用以下代码替换 `Program.cs` 中的代码。

   ```
   using AWS.Messaging;
   using Handler;
   using Microsoft.Extensions.DependencyInjection;
   using Microsoft.Extensions.Hosting;
   
   var builder = Host.CreateDefaultBuilder(args);
   
   builder.ConfigureServices(services =>
   {
       // Register the AWS Message Processing Framework for .NET.
       services.AddAWSMessageBus(builder =>
       {
           // Check for input SQS URL.
           // The SQS URL should be passed as a command line argument or set in the Debug launch profile.
           if ((args.Length == 1) && (args[0].Contains("https://sqs.")))
           {
               // Register you'll poll the following queue.
               builder.AddSQSPoller(args[0]);
   
               // And that messages of type "greetingMessage" should be:
               // 1. Deserialized as GreetingMessage objects.
               // 2. Which are then passed to GreetingMessageHandler.
               builder.AddMessageHandler<GreetingMessageHandler, GreetingMessage>("greetingMessage");
   
           }
           // You can add additional message handlers here, using different message types. 
       });
   });
   
   var host = builder.Build();
   await host.RunAsync();
   
   namespace Handler
   {
       /// <summary>
       /// This class represents the message contents.
       /// </summary>
       public class GreetingMessage
       {
           public string? SenderName { get; set; }
           public string? Greeting { get; set; }
       }
   
       /// <summary>
       /// This handler is invoked each time you receive the message.
       /// </summary>
       public class GreetingMessageHandler : IMessageHandler<GreetingMessage>
       {
           public Task<MessageProcessStatus> HandleAsync(
               MessageEnvelope<GreetingMessage> messageEnvelope,
               CancellationToken token = default)
           {
               Console.WriteLine(
                   $"Received message {messageEnvelope.Message.Greeting} from {messageEnvelope.Message.SenderName}");
               return Task.FromResult(MessageProcessStatus.Success());
           }
       }
   }
   ```

1. 运行以下命令。这会启动一个长时间运行的轮询器。

   ```
   dotnet run <queue URL created earlier>
   ```

   启动后不久，应用程序将收到本教程第一部分中发送的消息并记录以下消息：

   ```
   Received message {greeting} from {senderName}
   ```

1. 按 `Ctrl+C` 停止轮询器。

### 清理
<a name="mpf-tutorial-cleanup"></a>

使用 Amazon CLI 或 Amazon Tools for PowerShell 的以下命令之一删除队列。

------
#### [ Amazon CLI ]

```
aws sqs delete-queue --queue-url "<queue URL created earlier>"
```

------
#### [ Amazon Tools for PowerShell ]

```
Remove-SQSQueue -QueueUrl "<queue URL created earlier>"
```

------

# 使用 Amazon Message Processing Framework for .NET 发布消息
<a name="msg-proc-fw-publish"></a>

Amazon Message Processing Framework for .NET 支持发布一种或多种消息类型、处理一种或多种消息类型，或者在同一个应用程序中同时执行这两种操作。

以下代码显示了向不同 Amazon 服务发布不同消息类型的应用程序的配置。

```
var builder = WebApplication.CreateBuilder(args);

// Register the AWS Message Processing Framework for .NET
builder.Services.AddAWSMessageBus(builder =>
{
    // Register that you'll send messages of type ChatMessage to an existing queue
    builder.AddSQSPublisher<ChatMessage>("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd");

    // Register that you'll publish messages of type OrderInfo to an existing SNS topic
    builder.AddSNSPublisher<OrderInfo>("arn:aws:sns:us-west-2:012345678910:MyAppProd");

    // Register that you'll publish messages of type FoodItem to an existing EventBridge bus
    builder.AddEventBridgePublisher<FoodItem>("arn:aws:events:us-west-2:012345678910:event-bus/default");
});
```

在启动过程中注册框架后，将通用 `IMessagePublisher` 注入到代码中。调用其 `PublishAsync` 方法来发布上面配置的任何消息类型。通用发布者将根据消息类型确定要将消息路由到的目的地。

 在以下示例中，ASP.NET MVC 控制器接收来自用户的 `ChatMessage` 消息和 `OrderInfo` 事件，然后分别将其发布到 Amazon SQS 和 Amazon SNS。两种消息类型都可以使用上面配置的通用发布者发布。

```
[ApiController]
[Route("[controller]")]
public class PublisherController : ControllerBase
{
    private readonly IMessagePublisher _messagePublisher;

    public PublisherController(IMessagePublisher messagePublisher)
    {
        _messagePublisher = messagePublisher;
    }

    [HttpPost("chatmessage", Name = "Chat Message")]
    public async Task<IActionResult> PublishChatMessage([FromBody] ChatMessage message)
    {
        // Perform business and validation logic on the ChatMessage here.
        if (message == null)
        {
            return BadRequest("A chat message was not submitted. Unable to forward to the message queue.");
        }
        if (string.IsNullOrEmpty(message.MessageDescription))
        {
            return BadRequest("The MessageDescription cannot be null or empty.");
        }

        // Send the ChatMessage to SQS, using the generic publisher.
        await _messagePublisher.PublishAsync(message);

        return Ok();
    }

    [HttpPost("order", Name = "Order")]
    public async Task<IActionResult> PublishOrder([FromBody] OrderInfo message)
    {
        if (message == null)
        {
            return BadRequest("An order was not submitted.");
        }

        // Publish the OrderInfo to SNS, using the generic publisher.
        await _messagePublisher.PublishAsync(message);

        return Ok();
    }
}
```

为了将消息路由到相应的处理逻辑，框架使用称为*消息类型标识符*的元数据。默认情况下，这是消息的 .NET 类型的完整名称，包括其程序集名称。如果既要发送消息，又要处理消息，那么当跨项目共享消息对象的定义时，这种机制能很好地发挥作用。但是，如果在不同的命名空间中重新定义消息，或者您要与其他框架或编程语言交换消息，则可能需要覆盖消息类型标识符。

```
var builder = Host.CreateDefaultBuilder(args);

builder.ConfigureServices(services =>
{
    // Register the AWS Message Processing Framework for .NET
    services.AddAWSMessageBus(builder =>
    {
        // Register that you'll publish messages of type GreetingMessage to an existing queue
        builder.AddSQSPublisher<GreetingMessage>("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd", "greetingMessage");
    });
});
```

## 特定于服务的发布者
<a name="service-specific-publishers"></a>

上面显示的示例使用通用 `IMessagePublisher`，它可以根据配置的消息类型发布到任何支持的 Amazon 服务。该框架还为 Amazon SQS、Amazon SNS 和 Amazon EventBridge 提供特定于服务的发布者。这些特定的发布者会显示仅适用于特定服务的选项，并且这些选项可以使用类型 `ISQSPublisher`、`ISNSPublisher` 和 `IEventBridgePublisher` 完成注入。

例如，向 SQS FIFO 队列发送消息时，您必须设置相应的[消息组 ID](https://docs.amazonaws.cn/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-key-terms.html)。以下代码显示的还是 `ChatMessage` 示例，但这次使用 `ISQSPublisher` 来设置特定于 SQS 的选项。

```
public class PublisherController : ControllerBase
{
    private readonly ISQSPublisher _sqsPublisher;

    public PublisherController(ISQSPublisher sqsPublisher)
    {
        _sqsPublisher = sqsPublisher;
    }

    [HttpPost("chatmessage", Name = "Chat Message")]
    public async Task<IActionResult> PublishChatMessage([FromBody] ChatMessage message)
    {
        // Perform business and validation logic on the ChatMessage here
        if (message == null)
        {
            return BadRequest("A chat message was not submitted. Unable to forward to the message queue.");
        }
        if (string.IsNullOrEmpty(message.MessageDescription))
        {
            return BadRequest("The MessageDescription cannot be null or empty.");
        }

        // Send the ChatMessage to SQS using the injected ISQSPublisher, with SQS-specific options
        await _sqsPublisher.SendAsync(message, new SQSOptions
        {
            DelaySeconds = <delay-in-seconds>,
            MessageAttributes = <message-attributes>,
            MessageDeduplicationId = <message-deduplication-id>,
            MessageGroupId = <message-group-id>
        });

        return Ok();
    }
}
```

对于 SNS 和 EventBridge，也可以分别使用 `ISNSPublisher` 和 `IEventBridgePublisher` 来完成同样的操作。

```
await _snsPublisher.PublishAsync(message, new SNSOptions
{
    Subject = <subject>,
    MessageAttributes = <message-attributes>,
    MessageDeduplicationId = <message-deduplication-id>,
    MessageGroupId = <message-group-id>
});
```

```
await _eventBridgePublisher.PublishAsync(message, new EventBridgeOptions
{
    DetailType = <detail-type>,
    Resources = <resources>,
    Source = <source>,
    Time = <time>,
    TraceHeader = <trace-header>
});
```

默认情况下，给定类型的消息会发送到预先配置的目的地。但是，您可以使用特定于消息的发布者来覆盖单条消息的目的地。您还可以覆盖用于发布消息的底层 适用于 .NET 的 Amazon SDK 客户端，这在需要根据目的地更改角色或凭证的多租户应用程序中非常有用。

```
await _sqsPublisher.SendAsync(message, new SQSOptions
{
    OverrideClient = <override IAmazonSQS client>,
    QueueUrl = <override queue URL>
});
```

# 借助 Amazon Message Processing Framework for .NET 来使用消息
<a name="msg-proc-fw-consume"></a>

Amazon Message Processing Framework for .NET 使您能够使用通过该框架或其中一个消息收发服务[发布的](msg-proc-fw-publish.md)消息。这些消息可以通过多种方式使用，其中一些方式如下所述。

## 消息处理程序
<a name="handle-a-message"></a>

要使用消息，请使用 `IMessageHandler` 接口为要处理的每种消息类型实施消息处理程序。消息类型和消息处理程序之间的映射是在项目启动时配置的。

```
await Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        // Register the AWS Message Processing Framework for .NET
        services.AddAWSMessageBus(builder =>
        {
            // Register an SQS Queue that the framework will poll for messages.
            // NOTE: The URL given below is an example. Use the appropriate URL for your SQS Queue.
            builder.AddSQSPoller("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd");

            // Register all IMessageHandler implementations with the message type they should process. 
            // Here messages that match our ChatMessage .NET type will be handled by our ChatMessageHandler
            builder.AddMessageHandler<ChatMessageHandler, ChatMessage>();
        });
    })
    .Build()
    .RunAsync();
```

以下代码显示了 `ChatMessage` 消息的示例消息处理程序。

```
public class ChatMessageHandler : IMessageHandler<ChatMessage>
{
    public Task<MessageProcessStatus> HandleAsync(MessageEnvelope<ChatMessage> messageEnvelope, CancellationToken token = default)
    {
        // Add business and validation logic here.
        if (messageEnvelope == null)
        {
            return Task.FromResult(MessageProcessStatus.Failed());
        }

        if (messageEnvelope.Message == null)
        {
            return Task.FromResult(MessageProcessStatus.Failed());
        }

        ChatMessage message = messageEnvelope.Message;

        Console.WriteLine($"Message Description: {message.MessageDescription}");

        // Return success so the framework will delete the message from the queue.
        return Task.FromResult(MessageProcessStatus.Success());
    }
}
```

外部 `MessageEnvelope` 包含框架使用的元数据。它的 `message` 属性是消息类型（在本例中为 `ChatMessage`）。

您可以返回 `MessageProcessStatus.Success()` 以表明消息已成功处理，框架将从 Amazon SQS 队列中删除该消息。返回 `MessageProcessStatus.Failed()` 时，消息将保留在队列中，以便再次得到处理或移至[死信队列](https://docs.amazonaws.cn/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html)（如果已配置）。

## 在长时间运行的进程中处理消息
<a name="long-running-process"></a>

您可以使用 SQS 队列 URL 调用 `AddSQSPoller` 以启动一个长时间运行的 [https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.backgroundservice](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.backgroundservice)，该服务将持续轮询队列并处理消息。

```
await Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        // Register the AWS Message Processing Framework for .NET
        services.AddAWSMessageBus(builder =>
        {
            // Register an SQS Queue that the framework will poll for messages.
            // NOTE: The URL given below is an example. Use the appropriate URL for your SQS Queue.
            builder.AddSQSPoller("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd", options => 
            {
                // The maximum number of messages from this queue that the framework will process concurrently on this client.
                options.MaxNumberOfConcurrentMessages = 10;

                // The duration each call to SQS will wait for new messages.
                options.WaitTimeSeconds = 20; 
            });

            // Register all IMessageHandler implementations with the message type they should process.
            builder.AddMessageHandler<ChatMessageHandler, ChatMessage>();
        });
    })
    .Build()
    .RunAsync();
```

### 配置 SQS 消息轮询器
<a name="config-msg-poller"></a>

SQS 消息轮询器可在调用 `AddSQSPoller` 时通过 `SQSMessagePollerOptions` 进行配置。
+ `MaxNumberOfConcurrentMessages` - 队列中可同时处理的最大消息数量。默认值是 10。
+ `WaitTimeSeconds` - `ReceiveMessage` SQS 调用在返回前等待队列中消息到达的时间（以秒为单位）。如果消息可用，则调用会早于 `WaitTimeSeconds` 返回。默认值为 20。

**消息可见性超时处理**

SQS 消息有[可见性超时](https://docs.amazonaws.cn/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-visibility-timeout.html)时段。当一个使用者开始处理给定消息时，该消息仍会保留在队列中，但对其他使用者不可见，以避免重复处理。如果消息在再次可见之前未被处理和删除，则其他使用者可能会尝试处理同一条消息。

该框架将跟踪并尝试延长其当前正在处理的消息的可见性超时时间。您可以在调用 `AddSQSPoller` 时在 `SQSMessagePollerOptions` 上配置此行为。
+ `VisibilityTimeout` - 接收到的消息对后续检索请求不可见的时长（以秒为单位）。默认值为 30。
+ `VisibilityTimeoutExtensionThreshold` - 当消息的可见性超时时间距离到期剩余此秒数时，框架将延长可见性超时时间（再增加 `VisibilityTimeout` 秒）。默认值是 5。
+ `VisibilityTimeoutExtensionHeartbeatInterval` - 框架检查距离过期时间不足 `VisibilityTimeoutExtensionThreshold` 秒的消息并延长其可见性超时时间的频率（以秒为单位）。默认值是 1。

 在以下示例中，框架将每 1 秒检查一次仍在处理中的消息。对于在 5 秒内会再次可见的消息，框架会自动将每条消息的可见性超时时间再延长 30 秒。

```
// NOTE: The URL given below is an example. Use the appropriate URL for your SQS Queue.
builder.AddSQSPoller("https://sqs.us-west-2.amazonaws.com/012345678910/MyAppProd", options => 
{
    options.VisibilityTimeout = 30;
    options.VisibilityTimeoutExtensionThreshold = 5;
    VisibilityTimeoutExtensionHeartbeatInterval = 1;
});
```

## 在 Amazon Lambda 函数中处理消息
<a name="lambda-functions"></a>

您可以将 Amazon Message Processing Framework for .NET 和 [SQS 与 Lambda 的集成](https://docs.amazonaws.cn/lambda/latest/dg/with-sqs.html)结合使用。这是由 `AWS.Messaging.Lambda` 软件包提供的。请参阅其[自述文件](https://github.com/aws/aws-dotnet-messaging/blob/main/src/AWS.Messaging.Lambda/README.md)开始使用。

# 将 FIFO 与 Amazon Message Processing Framework for .NET 结合使用
<a name="msg-proc-fw-fifo"></a>

对于消息排序和消息重复数据删除至关重要的使用案例，Amazon Message Processing Framework for .NET 支持先进先出（FIFO）[Amazon SQS 队列](https://docs.amazonaws.cn/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-fifo-queues.html)和 [Amazon SNS 主题](https://docs.amazonaws.cn/sns/latest/dg/sns-fifo-topics.html)。

## 发布
<a name="mpf-fifo-publish"></a>

向 FIFO 队列或主题发布消息时，您必须设置消息组 ID，该 ID 指定消息所属的组。组内的消息按顺序处理。您可以在特定于 SQS 和 SNS 的消息发布者上进行此设置。

```
await _sqsPublisher.PublishAsync(message, new SQSOptions
{
    MessageDeduplicationId = <message-deduplication-id>,
    MessageGroupId = <message-group-id>
});
```

## 订阅
<a name="mpf-fifo-subscribe"></a>

处理来自 FIFO 队列的消息时，框架会按照每次 `ReceiveMessages` 调用的接收顺序处理给定消息组中的消息。当配置以 `.fifo` 结尾的队列时，框架会自动进入此操作模式。

```
await Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        // Register the AWS Message Processing Framework for .NET.
        services.AddAWSMessageBus(builder =>
        {
            // Because this is a FIFO queue, the framework automatically handles these messages in order.
            builder.AddSQSPoller("https://sqs.us-west-2.amazonaws.com/012345678910/MPF.fifo");
            builder.AddMessageHandler<OrderMessageHandler, OrderMessage>();
        });
    })
    .Build()
    .RunAsync();
```

# Amazon Message Processing Framework for .NET 的日志记录和 OpenTelemetry
<a name="msg-proc-fw-telemetry"></a>

Amazon Message Processing Framework for .NET 已集成 OpenTelemetry，可记录该框架发布或处理的每条消息的[追踪信息](https://opentelemetry.io/docs/concepts/signals/traces/)。这是由 [https://www.nuget.org/packages/AWS.Messaging.Telemetry.OpenTelemetry](https://www.nuget.org/packages/AWS.Messaging.Telemetry.OpenTelemetry) 软件包提供的。请参阅其[自述文件](https://github.com/aws/aws-dotnet-messaging/blob/main/src/AWS.Messaging.Telemetry.OpenTelemetry/README.md)开始使用。

**注意**  
有关日志记录的安全性信息，请参阅[Amazon Message Processing Framework for .NET 的安全性](msg-proc-fw-security.md)。

# 自定义 Amazon Message Processing Framework for .NET
<a name="msg-proc-fw-customize"></a>

Amazon Message Processing Framework for .NET 在三个不同的“层”中构建、发送和处理消息：

1. 在最外层，框架构建特定于服务的 Amazon 原生请求或响应。例如，在 Amazon SQS 中，它生成 [https://docs.amazonaws.cn/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html](https://docs.amazonaws.cn/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html) 请求并处理该服务定义的 [https://docs.amazonaws.cn/AWSSimpleQueueService/latest/APIReference/API_Message.html](https://docs.amazonaws.cn/AWSSimpleQueueService/latest/APIReference/API_Message.html) 对象。

1. 在 SQS 请求和响应中，框架将 `MessageBody` 元素（对于 Amazon SNS，为 `Message`，对于 Amazon EventBridge，为 `Detail`）设置为 [JSON 格式的 CloudEvent](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md)。它包含框架设置的元数据，在处理消息时可在 `MessageEnvelope` 对象上访问。

1. 在最内层，CloudEvent JSON 对象内的 `data` 属性包含一个 JSON 序列化表示的 .NET 对象，该对象作为消息发送或接收。

   ```
   {
       "id":"b02f156b-0f02-48cf-ae54-4fbbe05cffba",
       "source":"/aws/messaging",
       "specversion":"1.0",
       "type":"Publisher.Models.ChatMessage",
       "time":"2023-11-21T16:36:02.8957126+00:00",
       "data":"<the ChatMessage object serialized as JSON>"
   }
   ```

您可以自定义消息信封的配置方式和读取方式：
+ `"id"` 是消息的唯一标识符。它默认设置为新的 GUID，但是您可以实施自己的 `IMessageIdGenerator` 并将其注入 DI 容器来覆盖此设置。
+ `"type"` 控制消息路由到处理程序的方式。默认情况下，此设置使用与消息对应的 .NET 类型的完整名称。当通过 `AddSQSPublisher`、`AddSNSPublisher` 或 `AddEventBridgePublisher` 将消息类型映射到目的地时，您可以通过 `messageTypeIdentifier` 参数覆盖此设置。
+ `"source"` 表示发送消息的系统或服务器。
  + 如果从 Amazon Lambda 发布，则该值是函数名称；如果在 Amazon ECS 上，则该值为集群名称和任务 ARN；如果在 Amazon EC2 上，则该值为实例 ID，否则为 `/aws/messaging` 的回退值。
  + 您可以在 `MessageBusBuilder` 上通过 `AddMessageSource` 或 `AddMessageSourceSuffix` 覆盖此设置。
+ `"time"` 设置为当前的日期时间（UTC）。您可以通过实施自己的 `IDateTimeHandler` 并将其注入 DI 容器来覆盖此设置。
+ `"data"` 包含作为消息发送或接收的 .NET 对象的 JSON 表示：
  + `MessageBusBuilder` 上的 `ConfigureSerializationOptions` 让您能够配置序列化和反序列化消息时将使用的 [https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions](https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions)。
  + 要注入其他属性或在框架构建消息信封后对其进行转换，您可以实施 `ISerializationCallback` 并通过 `MessageBusBuilder` 上的 `AddSerializationCallback` 注册它。

# Amazon Message Processing Framework for .NET 的安全性
<a name="msg-proc-fw-security"></a>

Amazon Message Processing Framework for .NET 依赖适用于 .NET 的 Amazon SDK 与 Amazon 进行通信。有关 适用于 .NET 的 Amazon SDK 中安全性的更多信息，请参阅[本 Amazon 产品或服务的安全性](security.md)。

出于安全考虑，该框架不记录用户发送的数据消息。如果要出于调试目的启用此功能，则需要在 Message Bus 中调用 `EnableDataMessageLogging()`，如下所示：

```
builder.Services.AddAWSMessageBus(bus =>
{
    builder.EnableDataMessageLogging();
});
```

如果您发现潜在的安全问题，请参阅[安全策略](https://github.com/aws/aws-dotnet-messaging/security/policy)以获取报告信息。

# 在 适用于 .NET 的 Amazon SDK 中将 Amazon 与 .NET Aspire 集成
<a name="aspire-integrations"></a>

.NET Aspire 是一种构建云就绪型应用程序的新方法。它专门为本地环境提供了一种编排工具，用于运行、连接和调试分布式应用程序的组件。为了改善云就绪型应用程序的内部开发循环，我们构建了与 .NET Aspire 的集成，用于将 .NET 应用程序连接到 Amazon 资源。这些集成可通过 [Aspire.Hosting.AWS](https://www.nuget.org/packages/Aspire.Hosting.AWS) NuGet 软件包获取。

以下.NET Aspire 集成可用：
+ 通过 [Amazon CloudFormation](https://www.amazonaws.cn/cloudformation/) 预置 Amazon 资源的功能。这种集成可用于 .NET Aspire AppHost 项目。

  有关更多信息，请参阅博客文章 [Integrating Amazon with .NET Aspire](https://www.amazonaws.cn/blogs/developer/integrating-aws-with-net-aspire/)。
+ 安装和配置 适用于 .NET 的 Amazon SDK 并将其连接到 [Amazon DynamoDB local](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/DynamoDBLocalHistory.html)。这种集成可用于 .NET Aspire AppHost 项目。

  有关更多信息，请参阅博客文章 [Integrating Amazon with .NET Aspire](https://www.amazonaws.cn/blogs/developer/integrating-aws-with-net-aspire/)。
+ 为 [Amazon Lambda](https://www.amazonaws.cn/lambda/) 函数启用本地开发环境。这种集成可用于 .NET Aspire AppHost 项目。

  有关更多信息，请参阅博客文章 [Building and Debugging .NET Lambda applications with .NET Aspire (Part 1)](https://www.amazonaws.cn/blogs/developer/building-lambda-with-aspire-part-1/) 和 [Building and Debugging .NET Lambda applications with .NET Aspire (Part 2)](https://www.amazonaws.cn/blogs/developer/building-lambda-with-aspire-part-2/)。
**注意**  
这是适用于预览版中特征的预发行文档。本文档随时可能更改。

  由于此功能为预览版，因此您需要选择加入来启用预览功能。有关此预览功能以及如何选择加入的更多信息，请参阅 [GitHub 上的开发跟踪器问题](https://github.com/aws/integrations-on-dotnet-aspire-for-aws/issues/17)。

## 其他信息
<a name="aspire-integrations-additional"></a>

有关 [Aspire.Hosting.AWS](https://www.nuget.org/packages/Aspire.Hosting.AWS) 中提供的集成的更多信息以及详细使用说明，请参阅以下资源。
+ 博客文章 [Integrating Amazon with .NET Aspire](https://www.amazonaws.cn/blogs/developer/integrating-aws-with-net-aspire/)。
+ 博客文章 [Building and Debugging .NET Lambda applications with .NET Aspire (Part 1)](https://www.amazonaws.cn/blogs/developer/building-lambda-with-aspire-part-1/) 和 [Building and Debugging .NET Lambda applications with .NET Aspire (Part 2)](https://www.amazonaws.cn/blogs/developer/building-lambda-with-aspire-part-2/)。
+ GitHub 上的 [integrations-on-dotnet-aspire-for-aws](https://github.com/aws/integrations-on-dotnet-aspire-for-aws) 存储库。
+ [Aspire.Hosting.AWS](https://www.nuget.org/packages/Aspire.Hosting.AWS) NuGet 软件包的详细[自述文件](https://github.com/aws/integrations-on-dotnet-aspire-for-aws/blob/main/src/Aspire.Hosting.AWS/README.md)。