

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# Amazon MQ for RabbitMQ 中訊息耐用性和可靠性的最佳實務
<a name="best-practices-message-reliability"></a>

 將應用程式移至生產環境之前，請完成下列最佳實務，以防止訊息遺失和資源過度使用。

## 步驟 1：使用持久性訊息和持久性佇列
<a name="use-persistent-messages-durable-queues"></a>

 持久性訊息有助於在代理程式當機或重新啟動的情況下保護資料耐久性。持續性訊息會在送達磁碟時立即寫入。然而，與延遲佇列不同，除非代理程式需要更多記憶體，否則持續性訊息會在記憶體和磁碟中快取。在需要更多記憶體的情況下，訊息由管理將訊息儲存到磁碟的 RabbitMQ 代理程式機制從記憶體中刪除，通常稱為*持續性層*。

若要啟用訊息持續性，您可以將佇列宣告為 `durable`，並將訊息傳遞模式設定為 `persistent`。以下範例示範如何使用 [RabbitMQ Java 用戶端程式庫](https://www.rabbitmq.com/java-client.html)宣告耐久的佇列。使用 AMQP 0-9-1 時，您可以透過設定交付模式 "2"，將訊息標記為持久性。

```
boolean durable = true;
channel.queueDeclare("my_queue", durable, false, false, null);
```

 將佇列設定為耐久後，您可將 `MessageProperties` 設定為 `PERSISTENT_TEXT_PLAIN` (如以下範例所示)，將持續性訊息傳送到您的佇列。

```
import com.rabbitmq.client.MessageProperties;

channel.basicPublish("", "my_queue",
            MessageProperties.PERSISTENT_TEXT_PLAIN,
            message.getBytes());
```

## 步驟 2：設定發佈者確認和消費者交付確認
<a name="configure-confirmation-acknowledgement"></a>

 確認訊息已傳送至代理程式的程序稱為*發佈者確認*。發佈者確認讓應用程式知道訊息何時可靠地存放。發佈者確認也有助於控制存放在代理程式的訊息速率。如果沒有發佈者確認，則無法確認訊息已成功處理，而且您的代理程式可能會捨棄無法處理的訊息。

 同樣地，當用戶端應用程式將訊息的交付確認和取用傳回給代理程式時，稱為*消費者交付確認*。確認和確認對於確保使用 RabbitMQ 代理程式時的資料安全至關重要。

 消費者交付認可通常會設定於用戶端應用程式上。使用 AMQP 0-9-1 時，可以透過設定 `basic.consume`方法啟用確認。AMQP 0-9-1 用戶端也可以透過傳送 `confirm.select`方法來設定發佈者確認。

 通常，交付認可會在通道中啟用。例如，使用 RabbitMQ Java 用戶端程式庫時，您可使用 `Channel#basicAck` 來設定簡單的`basic.ack` 肯定認可，如以下範例所示。

```
// this example assumes an existing channel instance

boolean autoAck = false;
channel.basicConsume(queueName, autoAck, "a-consumer-tag",
     new DefaultConsumer(channel) {
         @Override
         public void handleDelivery(String consumerTag,
                                    Envelope envelope,
                                    AMQP.BasicProperties properties,
                                    byte[] body)
             throws IOException
         {
             long deliveryTag = envelope.getDeliveryTag();
             // positively acknowledge a single delivery, the message will
             // be discarded
             channel.basicAck(deliveryTag, false);
         }
     });
```

**注意**  
 未認可的訊息必須在記憶體中快取。您可設定用戶端應用程式的[預先擷取](best-practices-performance.md#configure-prefetching)設定，以限制消費者預先擷取的訊息數量。

 您可以設定 `consumer_timeout`來偵測消費者何時不確認交付。如果消費者未在逾時值內傳送確認，則頻道將會關閉，而您將會收到 `PRECONDITION_FAILED`。若要診斷錯誤，請使用 [UpdateConfiguration](https://docs.aws.amazon.com/amazon-mq/latest/api-reference/configurations-configuration-id.html) API 來增加`consumer_timeout`值。

## 步驟 3：讓佇列保持簡短
<a name="keep-queues-short"></a>

在叢集部署中，具有大量訊息的佇列可能會導致資源過度使用。當代理程式過度使用時，重新啟動 Amazon MQ for RabbitMQ 代理程式可能會導致效能進一步降低。若已重新啟動，過度使用的代理程式可能會在 `REBOOT_IN_PROGRESS` 狀態中變得沒有回應。

在[維護時段](amazon-mq-rabbitmq-editing-broker-preferences.md#rabbitmq-edit-current-configuration-console)期間，Amazon MQ 會一次執行一個節點的所有維護工作，以確保代理程式維持運作狀態。因此，佇列可能需要在每個節點繼續操作時進行同步處理。在同步期間，需要複寫到鏡像的訊息會從對應的 Amazon Elastic Block Store (Amazon EBS) 磁碟區載入記憶體中，以便分批處理。分批處理訊息可讓佇列更快速地同步處理。

如果佇列保持簡短且訊息很小，則佇列會成功同步處理並繼續如預期般操作。不過，如果批次中的資料量接近節點的記憶體限制，節點就會引發高記憶體警示，暫停佇列同步。您可比較 `RabbitMemUsed` 與 `RabbitMqMemLimit` [CloudWatch 中的代理程式節點指標](amazon-mq-accessing-metrics.md)，以確認記憶體使用量。直到取用或刪除訊息或減少批次中的訊息數目，才能完成同步處理。

 如果叢集部署暫停佇列同步處理，建議您取用或刪除訊息，以減少佇列中的訊息數目。一旦佇列深度減少且佇列同步完成，代理程式狀態就會變更為 `RUNNING`。若要解決暫停的佇列同步，您也可套用政策以[降低佇列同步處理批次大小](rabbitmq-queue-sync.md)。

您也可以定義自動刪除和 TTL 政策，以主動減少資源用量，並將消費者NACKs 保持在最低限度。在代理程式上重新排入佇列訊息是 CPU 密集型，因此大量的 NACKs 可能會影響代理程式效能。