

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

# Amazon MQ for ActiveMQ 最佳實務
<a name="best-practices-activemq"></a>

使用本節作為參考，快速找到在 Amazon MQ 上使用 ActiveMQ 代理程式時用於提升效能並降低輸送量成本的建議。

## 永不修改或刪除 Amazon MQ 彈性網路界面
<a name="never-modify-delete-elastic-network-interface"></a>

當您第一次[建立 Amazon MQ 代理程式](getting-started-activemq.md)時，Amazon MQ 會在 [Virtual Private Cloud (VPC)](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Introduction.html)中您的帳戶之下佈建[彈性網路界面](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_ElasticNetworkInterfaces.html)，因此，需要一些 [EC2 許可](security-api-authentication-authorization.md)。此網路界面可讓您的用戶端 (生產者或消費者) 與 Amazon MQ 代理程式通訊。儘管此網路界面是您帳戶 VPC 的一部分，因此被視為在 Amazon MQ 的*服務範圍*內。

**警告**  
您不得修改或刪除這個網路界面。修改或刪除網路界面可能導致永久遺失 VPC 與代理程式之間的連線。

![\[Diagram showing Client, Elastic Network Interface, and Amazon MQ Broker within a Customer VPC and service scope.\]](http://docs.aws.amazon.com/zh_tw/amazon-mq/latest/developer-guide/images/amazon-mq-network-configuration-architecture-vpc-elastic-network-interface.png)


## 一律使用連線集區
<a name="always-use-connection-pooling"></a>

在具有單一生產者和單一消費者的案例 (例如 [入門：建立並連線至 ActiveMQ 代理程式](getting-started-activemq.md) 教學課程) 中，您可以針對每個生產者和消費者使用單一 [http://activemq.apache.org/maven/apidocs/org/apache/activemq/ActiveMQConnectionFactory.html](http://activemq.apache.org/maven/apidocs/org/apache/activemq/ActiveMQConnectionFactory.html) 類別。例如：

```
// Create a connection factory.
final ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(wireLevelEndpoint);

// Pass the sign-in credentials.
connectionFactory.setUserName(activeMqUsername);
connectionFactory.setPassword(activeMqPassword);

// Establish a connection for the consumer.
final Connection consumerConnection = connectionFactory.createConnection();
consumerConnection.start();
```

不過，在具有多個生產者和消費者的更真實案例中，為多個生產者建立大量連線可能成本昂貴且效率不彰。在這些案例中，您應該使用 [http://activemq.apache.org/maven/apidocs/org/apache/activemq/jms/pool/PooledConnectionFactory.html](http://activemq.apache.org/maven/apidocs/org/apache/activemq/jms/pool/PooledConnectionFactory.html) 類別，將多個生產者請求分組。例如：

**注意**  
訊息消費者*不應*使用 `PooledConnectionFactory` 類別。

```
// Create a connection factory.
final ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(wireLevelEndpoint);

// Pass the sign-in credentials.
connectionFactory.setUserName(activeMqUsername);
connectionFactory.setPassword(activeMqPassword);

// Create a pooled connection factory.
final PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory();
pooledConnectionFactory.setConnectionFactory(connectionFactory);
pooledConnectionFactory.setMaxConnections(10);

// Establish a connection for the producer.
final Connection producerConnection = pooledConnectionFactory.createConnection();
producerConnection.start();
```

## 一律使用容錯移轉傳輸來連接到多個代理程式端點
<a name="always-use-failover-transport-connect-to-multiple-broker-endpoints"></a>

如果您需要將應用程式連接到多個代理程式端點 (例如，當您使用[作用中/待命](amazon-mq-broker-architecture.md#active-standby-broker-deployment)部署模式時，或當您[從內部部署訊息代理程式遷移至 Amazon MQ](https://docs.aws.amazon.com//amazon-mq/latest/migration-guide/) 時)，請使用[容錯移轉傳輸](http://activemq.apache.org/failover-transport-reference.html)，允許消費者隨機連接到其中一個。例如：

```
failover:(ssl://b-1234a5b6-78cd-901e-2fgh-3i45j6k178l9-1.mq.us-east-2.amazonaws.com:61617,ssl://b-9876l5k4-32ji-109h-8gfe-7d65c4b132a1-2.mq.us-west-2.amazonaws.com:61617)?randomize=true
```

**重要**  
 多可用區域代理程式可能會在維護時段和代理程式重新啟動期間遇到容錯移轉。使用容錯移轉傳輸以確保您的代理程式可用性。

## 避免使用訊息選取器
<a name="avoid-using-message-selectors"></a>

您可以使用 [JMS 選取器](https://docs.oracle.com/cd/E19798-01/821-1841/bncer/index.html)，將篩選條件附加到主題訂閱 (根據訊息的內容將訊息路由到消費者)。不過，使用 JMS 選取器會填滿 Amazon MQ 代理程式的篩選緩衝區，因而阻止它篩選訊息。

一般來說，請避免讓消費者路由訊息，因為為了讓消費者和生產者的去耦最佳化，消費者和生產者應該是暫時性。

## 比起耐久訂閱，更喜歡虛擬目的地
<a name="prefer-virtual-destinations-to-durable-subscriptions"></a>

例如，[耐久訂閱](http://activemq.apache.org/how-do-durable-queues-and-topics-work.html)可協助確保消費者在遺失的連線還原之後，會收到所有發佈到主題的訊息。不過，使用耐久訂閱也會排除競爭消費者的使用，而且可能發生大規模的效能問題。請考慮改用[虛擬目的地](http://activemq.apache.org/virtual-destinations.html)。

## 如果使用 Amazon VPC 對等互連，請避免使用 CIDR 範圍 `10.0.0.0/16` 內的用戶端 IP
<a name="best-practices-activemq-vpc-cidr-restriction"></a>

 如果您要在內部部署基礎設施與 Amazon MQ 代理程式之間設定 Amazon VPC 對等互連，則不得透過 CIDR 範圍 `10.0.0.0/16` 內的 IP 設定用戶端連線。

## 對於具有緩慢消費者的佇列，停用並行存放和分派
<a name="disable-concurrent-store-and-dispatch-queues-flag-slow-consumers"></a>

根據預設，Amazon MQ 會針對具有快速消費者的佇列而最佳化：
+ 如果消費者能夠跟得上生產者產生訊息的速率，則會將其視為*快速*消費者。
+ 如果佇列建置未認可訊息的後端記錄，這可能造成生產者傳輸量降低，則消費者會被視為*緩慢*。

若要指示 Amazon MQ 針對具有緩慢消費者的佇列來最佳化，請將 `concurrentStoreAndDispatchQueues` 屬性設定為 `false` 。如需範例組態，請參閱 [`concurrentStoreAndDispatchQueues`](child-element-details.md#concurrentStoreAndDispatchQueues)。

## 為最佳傳輸量選擇正確的代理程式執行個體類型
<a name="broker-instance-types-choosing"></a>

[代理程式執行個體類型](broker-instance-types.md)的訊息傳輸量取決於應用程式的使用案例和以下因素：
+ 在持久性模式中使用 ActiveMQ
+ 訊息大小
+ 生產者和消費者的數目
+ 目的地的數目

### 了解訊息大小、延遲和輸送量之間的關係
<a name="broker-instance-types-message-size-latency-throughput"></a>

根據您的使用案例，較大的代理程式執行個體類型可能不一定提高系統傳輸量。當 ActiveMQ 將訊息寫入到耐久性儲存時，訊息的大小決定系統的限制因素：
+ 如果您的訊息小於 100 KB，則持久性儲存延遲是限制因素。
+ 如果您的訊息大於 100 KB，則持久性儲存傳輸量是限制因素。

當您在持久性模式下使用 ActiveMQ 時，若有少數消費者或消費者是緩慢的，則通常會寫入至儲存。在非持久性模式下，如果代理程式執行個體的堆積記憶體已滿，則也會使用緩慢消費者寫入至儲存。

若要判斷您應用程式的最佳代理程式執行個體類型，我們建議測試不同的代理程式執行個體類型。如需詳細資訊，請參閱 [Amazon MQ for ActiveMQ 代理程式執行個體類型](broker-instance-types.md)，亦可參閱[使用 JMS 基準量測 Amazon MQ 的輸送量](https://aws.amazon.com/blogs/compute/measuring-the-throughput-for-amazon-mq-using-the-jms-benchmark/)。

### 大型代理程式執行個體類型的使用案例
<a name="broker-instance-types-larger-use-cases"></a>

當大型代理程式執行個體類型提高輸送量時，有三種常見的使用案例：
+ **非持久性模式** – 當您的應用程式對在[代理程式執行個體容錯移轉](amazon-mq-broker-architecture.md#active-standby-broker-deployment)期間失去訊息不太敏感時 (例如，當播放運動比分時)，您通常可以使用 ActiveMQ 的非持久性模式。在此模式下，僅在代理程式執行個體的堆積記憶體已滿時，ActiveMQ 才會將訊息寫入至持久性儲存。使用非持久性模式的系統可受益於大型代理程式執行個體類型上提供的更高記憶體數量、更快 CPU，以及更快網路。
+ **快速消費者** – 當作用中消費者可用，且 [`concurrentStoreAndDispatchQueues`](child-element-details.md#concurrentStoreAndDispatchQueues) 旗標已啟用時，ActiveMQ 可讓訊息直接從生產者移到消費者，無需將訊息傳送到儲存 (甚至在持久性模式下)。如果您的應用程式可以快速耗用訊息 (或如果您可以設計讓消費者這樣做)，則您的應用程式可受益於大型代理程式執行個體類型。若要讓您的應用程式更快耗用訊息，請將消費者執行緒新增到您的應用程式執行個體，或垂直或水平擴增您的應用程式執行個體。
+ **批次交易** – 當您使用持久性模式，並且為每個交易傳送多則訊息時，您可以使用大型代理程式執行個體類型來達到更高的整體訊息輸送量。如需詳細資訊，請參閱 Apache ActiveMQ 文件中的[我是否應使用交易](http://activemq.apache.org/should-i-use-transactions.html)。

## 為最佳輸送量選擇正確的代理程式儲存類型
<a name="broker-storage-types-choosing"></a>

若要利用跨多個可用區域的高耐久性和複寫功能，請使用 Amazon EFS。若要利用低延遲和高輸送量，請使用 Amazon EBS。如需詳細資訊，請參閱[Amazon MQ for ActiveMQ 儲存類型](broker-storage.md)。

## 正確地設定您的代理程式網路
<a name="network-of-brokers-configure-correctly"></a>

當您建立[代理程式網路](network-of-brokers.md)時，請為您的應用程式正確地設定此項目：
+ **啟用持久性模式** – 由於 (相對於同儕) 每個代理程式執行個體就像生產者或使用者，因此代理程式的網路並不提供分散式複寫的訊息。第一個做為使用者的代理程式，會接收訊息，並且將訊息儲存以持久保留。此代理程式會傳送認可訊息給生產者，並將該訊息轉傳給下一個代理程式。當第二個代理程式認可訊息的持久性時，第一個代理程式會刪除該訊息。

  如果已停用持久性模式，則第一個代理程式會發出認可訊息給生產者，而不會將訊息持久儲存。如需詳細資訊，請參閱 Apache ActiveMQ 文件中的 [Replicated Message Store (複製訊息存放)](http://activemq.apache.org/replicated-message-store.html) 和 [What is the difference between persistent and non-persistent delivery? (持久性與非持久性傳送的不同之處)](http://activemq.apache.org/what-is-the-difference-between-persistent-and-non-persistent-delivery.html)。
+ **不停用代理程式執行個體的建議訊息** – 如需詳細資訊，請參閱 Apache ActiveMQ 文件中的 [Advisory Message (建議訊息)](http://activemq.apache.org/advisory-message.html)。
+ **不使用多點傳送代理程式探索** – Amazon MQ 不支援使用多點傳送來探索代理程式。如需詳細資訊，請參閱 Apache ActiveMQ 文件中的 [What is the difference between discovery, multicast, and zeroconf? (探索、多點傳送和 zeroconf 的不同之處)](http://activemq.apache.org/multicast-transport-reference.html)。

## 透過復原備妥的 XA 交易避免緩慢重新啟動
<a name="recover-xa-transactions"></a>

ActiveMQ 支援分散式 (XA) 交易。了解 ActiveMQ 如何處理 XA 交易，有助於避免在 Amazon MQ 進行代理程式重新啟動和容錯移轉時出現緩慢的復原時間

每次重新啟動，都會重新播放未解決的備妥 XA 交易。如果這些交易仍未解決，則其數量會隨著時間增長，大幅增加啟動代理程式所需的時間。這會影響重新啟動和容錯移轉的時間。您必須使用 `commit()` 或 `rollback()` 解決這些交易，讓效能不會隨著時間降低。

若要監控未解決的備妥 XA 交易，您可以使用 Amazon CloudWatch Logs 中的 `JournalFilesForFastRecovery` 指標。如果此數量持續增加，或是一直高於 `1`，您應該使用類似以下範例的程式碼來復原未解決的交易。如需詳細資訊，請參閱[Amazon MQ 的配額](amazon-mq-limits.md)。

以下範例程式碼逐步解說備妥 XA 交易，並使用 `rollback()` 關閉它們。

```
import org.apache.activemq.ActiveMQXAConnectionFactory;

import javax.jms.XAConnection;
import javax.jms.XASession;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;

public class RecoverXaTransactions {
    private static final ActiveMQXAConnectionFactory ACTIVE_MQ_CONNECTION_FACTORY;
    final static String WIRE_LEVEL_ENDPOINT =
            "tcp://localhost:61616";;
    static {
        final String activeMqUsername = "MyUsername123";
        final String activeMqPassword = "MyPassword456";
        ACTIVE_MQ_CONNECTION_FACTORY = new ActiveMQXAConnectionFactory(activeMqUsername, activeMqPassword, WIRE_LEVEL_ENDPOINT);
        ACTIVE_MQ_CONNECTION_FACTORY.setUserName(activeMqUsername);
        ACTIVE_MQ_CONNECTION_FACTORY.setPassword(activeMqPassword);
    }

    public static void main(String[] args) {
        try {
            final XAConnection connection = ACTIVE_MQ_CONNECTION_FACTORY.createXAConnection();
            XASession xaSession = connection.createXASession();
            XAResource xaRes = xaSession.getXAResource();

            for (Xid id : xaRes.recover(XAResource.TMENDRSCAN)) {
                xaRes.rollback(id);
            }
            connection.close();

        } catch (Exception e) {          
        }
    }
}
```

在真實世界案例中，您可以針對 XA 交易管理員檢查您的備妥 XA 交易。然後，您可以決定是否要使用 `rollback()` 或 `commit()` 來處理每個備妥交易。