

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# ActiveMQ용 Amazon MQ 모범 사례
<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/ko_kr/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();
```

## 항상 Failover Transport를 사용하여 여러 브로커 엔드포인트에 연결
<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가 지속 가능한 스토리지에 메시지를 기록할 때 메시지 크기에 따라 시스템의 제한 요인이 결정됩니다.
+ 메시지 크기가 100KB보다 작으면 영구 스토리지 지연 시간이 제한 요인입니다.
+ 메시지 크기가 100KB보다 크면 영구 스토리지 처리량이 제한 요인입니다.

ActiveMQ가 지속 모드일 경우 소비자 수가 거의 없거나 소비자 속도가 느릴 때 스토리지에 대한 쓰기가 정상적으로 수행됩니다. 비지속 모드에서는 브로커 인스턴스의 힘 메모리가 가득 찰 경우 소비자 속도가 느려도 스토리지에 대한 쓰기가 수행됩니다.

애플리케이션에 가장 적합한 브로커 인스턴스를 확인하려면 다양한 브로커 인스턴스 유형을 검사하는 것이 좋습니다. 자세한 내용은 [ActiveMQ용 Amazon MQ 브로커 인스턴스 유형](broker-instance-types.md) 단원 및 [JMS Benchmark를 사용하여 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는 메시지를 스토리지로 전송하지 않고 메시지가 생산자에서 소비자로 직접 흐르도록 허용합니다(지속 모드에서도 허용). 애플리케이션이 메시지를 빨리 소비할 수 있으면(소비자가 이렇게 실행하도록 설계할 수 있으면) 애플리케이션은 더 큰 브로커 인스턴스 유형의 이점을 활용할 수 있습니다. 애플리케이션에서 메시지를 더 빠르게 소비할 수 있게 하려면 애플리케이션 인스턴스에 소비자 스레드를 추가하거나, 애플리케이션 인스턴스를 수직 또는 수평으로 확장합니다.
+ **배치 트랜잭션** - 지속 모드를 사용하며 트랜잭션당 여러 개의 메시지를 전송하는 경우 더 큰 브로커 인스턴스 유형을 사용하면 전체적으로 더 많은 메시지 처리량을 달성할 수 있습니다. 자세한 내용은 ActiveMQ 설명서의 [트랜잭션을 사용해야 합니까?](http://activemq.apache.org/should-i-use-transactions.html)를 참조하세요.

## 처리량을 최대화하기 위해 올바른 브로커 스토리지 유형 선택
<a name="broker-storage-types-choosing"></a>

다중 가용 영역에 걸친 높은 내구성 및 복제를 활용하려면 Amazon EFS를 사용하세요. 짧은 대기 시간 및 높은 처리량을 활용하려면 Amazon EBS를 사용하세요. 자세한 정보는 [ActiveMQ용 Amazon MQ 스토리지 유형](broker-storage.md)을 참조하세요.

## 브로커 네트워크를 올바로 구성
<a name="network-of-brokers-configure-correctly"></a>

[네트워크 브로커](network-of-brokers.md)를 생성할 때 애플리케이션에 올바르게 구성합니다.
+ **지속 모드를 활성화** - (피어에 비해) 각 브로커 인스턴스는 생산자 또는 소비자처럼 행동하기 때문에 브로커 네트워크는 분산된 메시지 복제를 제공하지 않습니다. 소비자로 행동하는 첫 번째 브로커가 메시지를 수신하고 스토리지에 지속시킵니다. 이 브로커는 생산자에게 승인을 전송하고 메시지를 다음 브로커에 전달합니다. 두 번째 브로커가 메시지의 지속성을 승인하고 첫 번째 브로커가 메시지를 삭제합니다.

  지속 모드가 비활성화된 경우, 첫 번째 브로커가 메시지를 스토리지에 지속시키지 않고 생산자를 승인합니다. 자세한 내용은 Apache ActiveMQ 설명서에서 [복제된 메시지 스토어](http://activemq.apache.org/replicated-message-store.html) 및 [지속적 전송과 비지속적 전송의 차이점은 무엇입니까?](http://activemq.apache.org/what-is-the-difference-between-persistent-and-non-persistent-delivery.html)를 참조하세요.
+ **브로커 인스턴스에 대해 자문 메시지를 비활성화하지 않음** - 자세한 내용은 Apache ActiveMQ 설명서에서 [자문 메시지](http://activemq.apache.org/advisory-message.html)를 참조하세요.
+ **멀티캐스트 브로커 검색을 사용하지 않음** - Amazon MQ는 멀티캐스트를 사용한 브로커 검색을 지원하지 않습니다. 자세한 내용은 Apache ActiveMQ 설명서에서 [검색, 멀티캐스트, 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 Transaction Manager와 비교하여 준비된 XA 트랜잭션을 확인할 수 있습니다. 그런 다음 각각의 준비된 트랜잭션을 `rollback()` 또는 `commit()` 중에서 어떤 것으로 처리할지 결정할 수 있습니다.