2015-04-21 15 views
5

Używam biblioteki klienta mq 3.4.1 java królika i nie mogę uzyskać działania mechanizmu automatycznego odzyskiwania.RabbitMQ: Mechanizm odzyskiwania połączenia

ten sposób tworzę królika fabrykę połączeń mq:

factory = new ConnectionFactory(); 
factory.setUsername(userName); 
factory.setPassword(password); 
factory.setVirtualHost(virtualHost); 
factory.setAutomaticRecoveryEnabled(true); 
factory.setNetworkRecoveryInterval(5); 
factory.setRequestedHeartbeat(3); 

Po publikacji komunikatu, jeśli zamknięcie broker mq królik i wnieść go ponownie, spodziewam mechanizm odzyskiwania kopać w i przywrócić połączenie do stanu "zdrowego". Ale pojawia się następujący błąd:

com.rabbitmq.client.AlreadyClosedException: connection is already closed due to connection error; protocol method: #method<connection.close>(reply-code=320, reply-text=CONNECTION_FORCED - broker forced connection closure with reason 'shutdown', class-id=0, method-id=0) 
    at com.rabbitmq.client.impl.AMQChannel.ensureIsOpen(AMQChannel.java:190) ~[amqp-client-3.4.1.jar:na] 
    at com.rabbitmq.client.impl.AMQChannel.transmit(AMQChannel.java:291) ~[amqp-client-3.4.1.jar:na] 
    at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:654) ~[amqp-client-3.4.1.jar:na] 
    at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:631) ~[amqp-client-3.4.1.jar:na] 
    at com.rabbitmq.client.impl.ChannelN.basicPublish(ChannelN.java:622) ~[amqp-client-3.4.1.jar:na] 

Czy tu brakuje mi czegoś? Jedynym sposobem obejścia tego problemu jest zarejestrowanie ShutDownListener i ponowne zainicjowanie fabryki połączenia, połączenia i kanałów królika mq.

także odpowiedzieć

"chrislott"

komentarz widzę odzyskanie auto kopiąc w celu odzyskania. Tworzę Exchange przy użyciu tymczasowy kanał:

Channel channel = connection.createChannel(); 
channel.exchangeDeclare(exchangeName, exchangeType, durable); 
channel.close(); 

I patrz poniższy wyjątek podczas jego próby odzyskania topologię:

Caught an exception when recovering topology Caught an exception while recovering exchange testSuccessfulInitVirtualHost_Exchange: channel is already closed due to clean channel shutdown; protocol method: #method<channel.close>(reply-code=200, reply-text=OK, class-id=0, method-id=0) 
com.rabbitmq.client.TopologyRecoveryException: Caught an exception while recovering exchange testSuccessfulInitVirtualHost_Exchange: channel is already closed due to clean channel shutdown; protocol method: #method<channel.close>(reply-code=200, reply-text=OK, class-id=0, method-id=0) 
    at com.rabbitmq.client.impl.recovery.AutorecoveringConnection.recoverExchanges(AutorecoveringConnection.java:482) 
    at com.rabbitmq.client.impl.recovery.AutorecoveringConnection.recoverEntities(AutorecoveringConnection.java:467) 
    at com.rabbitmq.client.impl.recovery.AutorecoveringConnection.beginAutomaticRecovery(AutorecoveringConnection.java:411) 
    at com.rabbitmq.client.impl.recovery.AutorecoveringConnection.access$000(AutorecoveringConnection.java:52) 
    at com.rabbitmq.client.impl.recovery.AutorecoveringConnection$1.shutdownCompleted(AutorecoveringConnection.java:351) 
    at com.rabbitmq.client.impl.ShutdownNotifierComponent.notifyListeners(ShutdownNotifierComponent.java:75) 
    at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:574) 

Powyższy wyjątek nie jest widoczny, jeśli nie zamknąć kanał używany do tworzenia wymiany.

Odpowiedz

2

Moje odczytanie metody ConnectionMactory # setAutomaticRecoveryEnabled (Boolean) polega na tym, że umożliwia ona przede wszystkim odtwarzanie po awarii NETWORK.

Oto miła dyskusja: https://www.rabbitmq.com/api-guide.html

Na przykład, jeśli urządzenie traci trasę do maklera na okres czasu, być może ze względu na przełączniku lub innej awarii, a następnie automatycznego odzyskiwania może ponownie ustanowić połączenie itp. Dokument nie mówi nic o przetrwaniu zamknięcia brokera/restarcie, nie sądzę, że twoje oczekiwania są rozsądne.

IMHO do odzyskania po ponownym uruchomieniu brokera, podejście shutdown-listener wydaje się być solidnym podejściem.

+0

Ale widzę, jak wraca automatyczne odzyskiwanie. Tworzę centralę za pomocą kanału tymczasowego: Channel channel = connection.createChannel(); channel.exchangeDeclare (exchangeName, exchangeType, durable); channel.close(); – user170008

1

Zwykle klient typu królik powinien obsługiwać samo odzyskiwanie - nie należy go ponownie ręcznie wdrażać. Przynajmniej spróbuj użyć lyra.

Podczas próby przełączania awaryjnego wystąpiły problemy. Połączenia mają tendencję do zawieszania się na zawsze po ponownym uruchomieniu brokera, więc wyjątek sygnału wyłączania był ostatnią rzeczą w dziennikach. Naprawiłem to, ustawiając:

factory.setConnectionTimeout(20_000); 

Również odzyskiwanie nie działało dobrze w przypadku tymczasowych kolejek. Jeśli masz te, prawdopodobnie będziesz musiał wykonać dodatkową obsługę (ponownie, spróbuj najpierw lyra).