

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

# RabbitMQ 教程
<a name="rabbitmq-on-amazon-mq"></a>

以下教程展示如何在 Amazon MQ 上配置和使用 RabbitMQ。要了解有关使用各种编程语言（如 Node.js、Python、.NET 等）支持的客户端库的更多信息，请参阅《RabbitMQ Getting Started Guide》**中的 [RabbitMQ Tutorials](https://www.rabbitmq.com/getstarted.html)。

**Topics**
+ [编辑代理首选项](amazon-mq-rabbitmq-editing-broker-preferences.md)
+ [将 Python Pika 与 Amazon MQ for RabbitMQ 结合使用](amazon-mq-rabbitmq-pika.md)
+ [解决 RabbitMQ 暂停队列同步的问题](rabbitmq-queue-sync.md)
+ [减少连接和通道的数量](reducing-connections-and-channels.md)
+ [步骤 2：将基于 JVM 的应用程序连接到代理](#rabbitmq-connect-jvm-application)
+ [Connect your Amazon MQ for RabbitMQ broker to Lambda](#rabbitmq-connect-to-lambda)
+ [为 Amazon MQ for RabbitMQ 使用 OAuth 2.0 认证与授权](oauth-tutorial.md)
+ [对适用于 RabbitMQ 的亚马逊 MQ 使用 IAM 身份验证和授权](rabbitmq-iam-tutorial.md)
+ [对适用于 RabbitMQ 的 Amazon MQ 使用 LDAP 身份验证和授权](rabbitmq-ldap-tutorial.md)
+ [对适用于 RabbitMQ 的亚马逊 MQ 使用 HTTP 身份验证和授权](rabbitmq-http-tutorial.md)
+ [对适用于 RabbitMQ 的亚马逊 MQ 使用 SSL 证书身份验证](rabbitmq-ssl-tutorial.md)
+ [将 mTLS 用于 AMQP 和管理端点](rabbitmq-mtls-tutorial.md)
+ [连接您的 JMS 应用程序](rabbitmq-tutorial-jms.md)

## 步骤 2：将基于 JVM 的应用程序连接到代理
<a name="rabbitmq-connect-jvm-application"></a>

 创建 RabbitMQ 代理后，您可以将应用程序连接到该代理。以下示例演示如何使用 [RabbitMQ Java 客户端库](https://www.rabbitmq.com/java-client.html)创建与您的代理的连接，创建队列并发送消息。您可以使用各种语言支持的 RabbitMQ 客户端库连接到 RabbitMQ 代理。有关支持的 RabbitMQ 客户端库的更多信息，请参阅 [RabbitMQ 客户端库和开发人员工具](https://www.rabbitmq.com/devtools.html)。

### 先决条件
<a name="rabbitmq-connect-application-prerequisites-getting-started"></a>

**注意**  
以下先决条件步骤仅适用于创建的没有公开可访问性的 RabbitMQ 代理。如果您正在创建具有公开可访问性的代理，则可以跳过它们。

#### 启用 VPC 属性
<a name="rabbitmq-connect-application-enable-vpc-attributes-getting-started"></a>

要确保您的代理可以在您的 VPC 中访问，您必须启用 `enableDnsHostnames` 和 `enableDnsSupport` VPC 属性。有关更多信息，请参阅《Amazon VPC 用户指南》**中的 [VPC 中的 DNS Support](https://docs.amazonaws.cn/vpc/latest/userguide/vpc-dns.html#vpc-dns-support)。

#### 启用入站连接
<a name="rabbitmq-connect-application-allow-inbound-connections-getting-started"></a>

1. 登录 [Amazon MQ 控制台](https://console.amazonaws.cn/amazon-mq/)。

1. 从经纪人列表中，选择您的经纪商的名称（例如 **MyBroker**）。

1. 在该***MyBroker***页面的 “**连接**” 部分，记下代理的 Web 控制台 URL 和线级协议的地址和端口。

1. 在 **Details (详细信息)** 部分的 **Security and network (安全与网络)** 下，选择您的安全组名称或 ![\[Pencil icon indicating an edit or modification action.\]](http://docs.amazonaws.cn/amazon-mq/latest/developer-guide/images/amazon-mq-tutorials-broker-details-link.png)。

   此时将显示 EC2 Dashboard 的 **Security Groups (安全组)** 页面。

1. 从安全组列表中，选择您的安全组。

1. 在页面底部，选择 **Inbound (入站)**，然后选择 **Edit (编辑)**。

1. 在 **Edit inbound rules (编辑入站规则)** 对话框中，为希望公开访问的每个 URL 或终端节点添加规则（以下示例显示如何为代理 Web 控制台执行此操作。

   1. 选择**添加规则**。

   1. 对于 **Type (类型)**，选择 **Custom TCP (自定义 TCP)**。

   1. 对于 **Source (源)**，选择 **Custom (自定义)**，然后键入您希望能够访问 Web 控制台的系统的 IP 地址（例如 `192.0.2.1`)。

   1. 选择**保存**。

      您的代理现在可以接受入站连接。

#### 添加 Java 依赖项
<a name="rabbitmq-connect-application-java-dependencies-getting-started"></a>

如果您使用 Apache Maven 进行自动构建，请将以下依赖项添加到您的 `pom.xml` 文件中。有关 Apache Maven 中项目对象模型文件的更多信息，请参阅 [POM 简介](https://maven.apache.org/guides/introduction/introduction-to-the-pom.html)。

```
<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>5.9.0</version>
</dependency>
```

如果您正在使用 [Gradle](https://docs.gradle.org/current/userguide/userguide.html) 进行自动构建，请声明以下依赖项。

```
dependencies {
    compile 'com.rabbitmq:amqp-client:5.9.0'
}
```

#### 导入 `Connection` 和 `Channel` 类
<a name="rabbitmq-import-connections-and-channels"></a>

 RabbitMQ Java 客户端使用 `com.rabbitmq.client` 作为其顶级软件包，`Connection` 和 `Channel` API 类分别表示 AMQP 0-9-1 连接和通道。使用前导入 `Connection` 和 `Channel` 类，如以下示例所示。

```
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
```

#### 创建 `ConnectionFactory` 并连接到您的代理
<a name="rabbitmq-create-connection-factory-and-connect"></a>

使用以下示例创建具有给定参数的 `ConnectionFactory` 类实例。使用 `setHost` 方法配置您之前记下的代理终端节点。对于 `AMQPS` 线级连接，请使用端口 `5671`。

```
ConnectionFactory factory = new ConnectionFactory();

factory.setUsername(username);
factory.setPassword(password);

//Replace the URL with your information
factory.setHost("b-c8352341-ec91-4a78-ad9c-a43f23d325bb.mq.us-west-2.amazonaws.com");
factory.setPort(5671);

// Allows client to establish a connection over TLS
factory.useSslProtocol();

// Create a connection
Connection conn = factory.newConnection();

// Create a channel
Channel channel = conn.createChannel();
```

#### 向交换器发布消息
<a name="rabbitmq-publish-message"></a>

 您可以使用 `Channel.basicPublish` 将消息发布到交换器。以下示例使用 AMQP `Builder` 类来构建具有内容类型 `plain/text` 的消息属性对象。

```
byte[] messageBodyBytes = "Hello, world!".getBytes();
channel.basicPublish(exchangeName, routingKey,
             new AMQP.BasicProperties.Builder()
               .contentType("text/plain")
               .userId("userId")
               .build(),
               messageBodyBytes);
```

**注意**  
请注意，`BasicProperties` 是自动生成的持有者类的内部类 `AMQP`。

#### 订阅队列并接收消息
<a name="rabbitmq-subscribe-receive-message"></a>

您可以通过使用 `Consumer` 接口订阅队列来接收消息。订阅后，消息将在到达时自动传递。

实现 `Consumer` 的最简单方法是使用子类 `DefaultConsumer`。`DefaultConsumer` 对象可以作为 `basicConsume` 调用的一部分传递以设置订阅，如以下示例所示。

```
boolean autoAck = false;
channel.basicConsume(queueName, autoAck, "myConsumerTag",
     new DefaultConsumer(channel) {
         @Override
         public void handleDelivery(String consumerTag,
                                    Envelope envelope,
                                    AMQP.BasicProperties properties,
                                    byte[] body)
             throws IOException
         {
             String routingKey = envelope.getRoutingKey();
             String contentType = properties.getContentType();
             long deliveryTag = envelope.getDeliveryTag();
             // (process the message components here ...)
             channel.basicAck(deliveryTag, false);
         }
     });
```

**注意**  
因为我们指定了 `autoAck = false`，所以必须确认传递到 `Consumer` 的消息，这在 `handleDelivery` 方法中完成最为方便，如示例所示。

#### 关闭连接并断开与代理的连接
<a name="rabbitmq-disconnect"></a>

要断开与您的 RabbitMQ 代理的连接，请关闭通道和连接，如下所示。

```
channel.close();
conn.close();
```

**注意**  
有关使用 RabbitMQ Java 客户端库的更多信息，请参阅 [RabbitMQ Java 客户端 API 指南](https://www.rabbitmq.com/api-guide.html)。

## 步骤 3：（可选）Connect 到 Amazon Lambda 函数
<a name="rabbitmq-connect-to-lambda"></a>

 Amazon Lambda 可以连接并使用来自您的 Amazon MQ 代理的消息。当您将代理连接到 Lambda 时，可以创建[事件源映射](https://docs.amazonaws.cn/lambda/latest/dg/invocation-eventsourcemapping.html)，从队列中读取消息并[同步](https://docs.amazonaws.cn/lambda/latest/dg/invocation-sync.html)调用函数。您创建的事件源映射分批从您的代理中读取消息，并以 JSON 对象的形式将它们转换为 Lambda 负载。

**将您的代理连接到 Lambda 函数**

1. 将以下 IAM 角色权限添加到 Lambda 函数[执行角色](https://docs.amazonaws.cn/lambda/latest/dg/lambda-intro-execution-role.html)。
   + [mq: DescribeBroker](https://docs.amazonaws.cn/amazon-mq/latest/api-reference/brokers-broker-id.html#brokers-broker-id-http-methods)
   + [ec2: CreateNetworkInterface](https://docs.amazonaws.cn/AWSEC2/latest/APIReference/API_CreateNetworkInterface.html)
   + [ec2: DeleteNetworkInterface](https://docs.amazonaws.cn/AWSEC2/latest/APIReference/API_DeleteNetworkInterface.html)
   + [ec2: DescribeNetworkInterfaces](https://docs.amazonaws.cn/AWSEC2/latest/APIReference/API_DescribeNetworkInterfaces.html)
   + [ec2: DescribeSecurityGroups](https://docs.amazonaws.cn/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
   + [ec2: DescribeSubnets](https://docs.amazonaws.cn/AWSEC2/latest/APIReference/API_DescribeSubnets.html)
   + [ec2: DescribeVpcs](https://docs.amazonaws.cn/AWSEC2/latest/APIReference/API_DescribeVpcs.html)
   + [日志：CreateLogGroup](https://docs.amazonaws.cn/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html)
   + [日志：CreateLogStream](https://docs.amazonaws.cn/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogStream.html)
   + [日志：PutLogEvents](https://docs.amazonaws.cn/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html)
   + [秘密管理器：GetSecretValue](https://docs.amazonaws.cn/secretsmanager/latest/apireference/API_GetSecretValue.html)
**注意**  
如果没有必要的 IAM 权限，您的函数将无法从 Amazon MQ 资源中成功读取记录。

1.  （可选）如果您创建了一个没有公开可访问性的代理，则必须执行下面其中一项操作以允许 Lambda 连接到您的代理：
   +  为每个公有子网配置一个 NAT 网关。有关更多信息，请参阅《Amazon Lambda 开发人员指南》**中的[VPC 连接函数的互联网和服务访问](https://docs.amazonaws.cn/lambda/latest/dg/configuration-vpc.html#vpc-internet)。
   + 使用 VPC 终端节点在您的 Amazon Virtual Private Cloud（Amazon VPC）和 Lambda 之间创建连接。您的 Amazon VPC 还必须连接到 Amazon Security Token Service (Amazon STS) 和 Secrets Manager 终端节点。有关更多信息，请参阅《Amazon Lambda 开发人员指南》**中的[为 Lambda 配置接口 VPC 终端节点](https://docs.amazonaws.cn/lambda/latest/dg/configuration-vpc-endpoints.html)。

1.  使用 Amazon Web Services 管理控制台为 Lambda 函数[配置代理作为事件源](https://docs.amazonaws.cn/lambda/latest/dg/with-mq.html#services-mq-eventsourcemapping)。您也可以使用该[https://docs.amazonaws.cn/cli/latest/reference/lambda/create-event-source-mapping.html](https://docs.amazonaws.cn/cli/latest/reference/lambda/create-event-source-mapping.html) Amazon Command Line Interface 命令。

1.  为 Lambda 函数编写一些代码来处理从您的代理使用的消息。事件源映射检索的 Lambda 负载取决于代理的引擎类型。以下是 Amazon MQ for RabbitMQ 队列的 Lambda 负载示例。
**注意**  
 在该示例中，`test` 是队列的名称，`/` 是默认虚拟主机的名称。接收消息时，事件源会将消息列在 `test::/` 下。

   ```
   {
     "eventSource": "aws:rmq",
     "eventSourceArn": "arn:aws:mq:us-west-2:112556298976:broker:test:b-9bcfa592-423a-4942-879d-eb284b418fc8",
     "rmqMessagesByQueue": {
       "test::/": [
         {
           "basicProperties": {
             "contentType": "text/plain",
             "contentEncoding": null,
             "headers": {
               "header1": {
                 "bytes": [
                   118,
                   97,
                   108,
                   117,
                   101,
                   49
                 ]
               },
               "header2": {
                 "bytes": [
                   118,
                   97,
                   108,
                   117,
                   101,
                   50
                 ]
               },
               "numberInHeader": 10
             }
             "deliveryMode": 1,
             "priority": 34,
             "correlationId": null,
             "replyTo": null,
             "expiration": "60000",
             "messageId": null,
             "timestamp": "Jan 1, 1970, 12:33:41 AM",
             "type": null,
             "userId": "AIDACKCEVSQ6C2EXAMPLE",
             "appId": null,
             "clusterId": null,
             "bodySize": 80
           },
           "redelivered": false,
           "data": "eyJ0aW1lb3V0IjowLCJkYXRhIjoiQ1pybWYwR3c4T3Y0YnFMUXhENEUifQ=="
         }
       ]
     }
   }
   ```

有关将 Amazon MQ 连接到 Lambda 的更多信息、Lambda 支持的 Amazon MQ 事件源选项以及事件源映射错误，请参阅[开发人员指南](https://docs.amazonaws.cn/lambda/latest/dg/with-mq.html)中的*Amazon Lambda 将 Lambda 与 Amazon MQ 结合使用*。