ActiveMQ 연결이 끊어지고 소비자가 일정 시간 동안 다시 연결하면 프로세스가 충돌하고 종료됩니다.

문제

최근에 문제가 발생했습니다 (activemq 버전은 5.14.5 임). 정상적인 ActiveMQ 연결이 끊어진 후에는 하트 비트 감지 및 재 연결 메커니즘으로 인해 장애 조치 방법을 사용하여 소비자가 실제로 계속해서 재 연결을 시도하며 프로세스는 항상 기존. 그러나 이상한 점은 mq가 연결 해제 된 후 일부 프로세스 소비자가 직접 전화를 끊는다는 것입니다. 로그 출력이없고 더 이상 다시 연결되지 않습니다.
주요 프로세스는 다음과 같으며 소비자 코드는 MessageListener를 정상적으로 설정하기위한 코드이므로 게시되지 않습니다.

/**
 * @author ZZJ
 * @description:
 * @date 2020-9-9 9:46
 */
public class ActiveMQTest {
    
    

    public static void main(String[] args) {
    
    

        ActiveMQConsumer activeMQConsumer = new ActiveMQConsumer();
        activeMQConsumer.consume();
    }
}

이유

비교를 통해 컨슈머 스레드 만 독립적으로 실행되는 프로세스에만 이러한 문제가 있음을 알 수 있으며, 쿼리 기간을 거쳐 ActiveMQ 자체 재 연결 메커니즘의 문제임을 알 수 있습니다.
전체 kimmking 답변 : 링크
는 간단합니다. ActiveMQ가 꺼져 있기 때문에 소켓 하트 비트가 응답을받을 수없고 일정 시간이 지나면 연결이 끊어 지지만 일반적으로 장애 조치 모드를 구성한 후 ActiveMQ 소비자 클라이언트는 스레드를 시작합니다. 다시 연결합니다. 같은

장애 조치 : (tcp : // broker1 : 61616, tcp : // broker2 : 61616)? maxReconnectAttempts = 1000 & initialReconnectDelay = 1000 & maxReconnectDelay = 300000 "

ActiveMQ에서 연결을 끊은 후 다시 연결할 브로커 URL 목록에서 브로커를 계속 선택합니다. maxReconnectAttempts 매개 변수는 최대 재 연결 횟수를 나타내며 initialReconnectDelay는 첫 번째 재 연결 후 1 초를 의미하고 다시 연결 후 1 초를 의미합니다. 시간은 매번 두 배가됩니다. 1 초, 2 초, 4 초, 8 초, maxReconnectDelay는 최대 재 연결 시간입니다.
그러나 재 연결 스레드는 데몬 스레드 (Daemon Thread)입니다.보다 대중적인 은유를 사용하기 위해 모든 데몬 스레드는 전체 JVM에서 모든 비 데몬 스레드의 보모입니다. 현재에 비 데몬 스레드가없는 한 JVM 인스턴스, 데몬 스레드는 모두 작동합니다. 데몬이 아닌 마지막 스레드가 종료 될 때만 데몬 스레드는 JVM으로 끝납니다. 데몬 쓰레드의 역할은 다른 쓰레드의 운영에 편리한 서비스를 제공하는 것입니다. 가장 일반적인 어플리케이션은 GC (garbage collector)입니다. 데몬이 아닌 쓰레드가 없을 경우 당연히 GC는 불필요하고 프로세스가 종료됩니다.
따라서이 문제의 원인은 매우 분명하다 : ActiveMQ 컨슈머 쓰레드 만 존재한다면 하트 비트가 응답을 받아들이지 않으면 소켓 연결이 끊어진다. 이때 재 연결 쓰레드가 있긴하지만 그것은 혼자 존재할 수 없기 때문이다. 는 데몬 스레드입니다., JVM은 데몬이 아닌 스레드가 없다고 판단하고 프로세스가 자연스럽게 종료됩니다.

풀다

첫 번째 방법

kimmking 메소드를 참조하고 재 연결 스레드 reconnectTaskFactory를 비 데몬 스레드로 설정하십시오.

activemq-all-5.8.0.jar! \ org \ apache \ activemq \ transport \ failover 경로 아래에 FailoverTransport.java를 추가합니다.

reconnectTaskFactory = new TaskRunnerFactory();
reconnectTaskFactory.setDaemon(false); // to set daemon=false by kimmking
reconnectTaskFactory.init();

jar 패키지를 수정하는 것이 번거롭기 때문에이 방법을 시도하지 않았지만 사용할 수 있어야합니다.

두 번째 방법
은 비교적 간단하고 어리석은 방법 입니다. 사실 비 데몬 스레드가 항상 존재하도록 스레드를 하나 더 설정하는 것입니다.이 방법은 최선은 아니지만이 스레드를 다음과 같이 설정하는 등 필요에 따라 사용할 수 있습니다. 타이밍 통계를 구현하고 소비자 및 기타 기능의 성공적인 소비 횟수를 출력합니다.

/**
 * @author ZZJ
 * @description:
 * @date 2020-9-9 9:46
 */
public class ActiveMQTest {
    
    
    public  static AtomicInteger count = new AtomicInteger();
    public static void main(String[] args) {
    
    

        ActiveMQConsumer activeMQConsumer = new ActiveMQConsumer();
        activeMQConsumer.consume();

        new Thread(() ->{
    
    
            while (true) {
    
    
                System.out.println("I'm alive");
                System.out.println("当前消费了" + count + "条消息");
                try {
    
    
                    Thread.sleep(60000);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

요약하자면

이 문제를 재현하기 위해 일시적으로 일련의 환경 테스트를 설정했는데 재현 할 수있는 문제가 더 이상 문제가되지 않는 것으로 나타났습니다.
ActiveMQ가 너무 오래되고, 처리량이 평균이고, 유지 보수가 좋지 않고, 인터넷에 정보가 많지 않고, 메시지가 손실 될 수 있습니다. 매우 오래된 프로젝트가 아닌 경우 RocketMQ와 같은 메시지 큐를 사용하는 것이 좋습니다.

추천

출처blog.csdn.net/qq_35530005/article/details/108527136