amqp - 在连接断开的情况下使用自动恢复

时间:2014-05-17 22:00:56

标签: java amqp

我试图在连接断开的情况下使用自动恢复功能。 我有两个问题:

1)自动恢复代码似乎完全忽略了networkRecoveryInterval。在我的日志文件中,连接断开的1分钟,文件增长到1.5 GB。以下错误不断重复。

  

在连接恢复期间发现异常!   java.net.SocketException:网络无法访问   java.net.PlainSocketImpl.socketConnect(Native Method)at   java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)     在   java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)     在   java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)     在java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)at   java.net.Socket.connect(Socket.java:579)at   com.rabbitmq.client.impl.FrameHandlerFactory.create(FrameHandlerFactory.java:32)     在   com.rabbitmq.client.impl.recovery.RecoveryAwareAMQConnectionFactory.newConnection(RecoveryAwareAMQConnectionFactory.java:34)     在   com.rabbitmq.client.impl.recovery.AutorecoveringConnection.recoverConnection(AutorecoveringConnection.java:388)     在   com.rabbitmq.client.impl.recovery.AutorecoveringConnection.beginAutomaticRecovery(AutorecoveringConnection.java:360)     在   com.rabbitmq.client.impl.recovery.AutorecoveringConnection.access $ 000(AutorecoveringConnection.java:48)     在   com.rabbitmq.client.impl.recovery.AutorecoveringConnection $ 1.shutdownCompleted(AutorecoveringConnection.java:345)     在   com.rabbitmq.client.impl.ShutdownNotifierComponent.notifyListeners(ShutdownNotifierComponent.java:75)     在   com.rabbitmq.client.impl.AMQConnection $ MainLoop.run(AMQConnection.java:572)     在java.lang.Thread.run(Thread.java:722)

2)最后当我打开路由器时,网络恢复不起作用。我在我的日志文件中得到了这个。

  

恢复拓扑时捕获异常同时捕获异常   恢复队列8923yrbk   com.rabbitmq.client.TopologyRecoveryException:捕获异常   同时恢复队列8923yrbk at   com.rabbitmq.client.impl.recovery.AutorecoveringConnection.recoverQueues(AutorecoveringConnection.java:459)     在   com.rabbitmq.client.impl.recovery.AutorecoveringConnection.recoverEntities(AutorecoveringConnection.java:424)     在   com.rabbitmq.client.impl.recovery.AutorecoveringConnection.beginAutomaticRecovery(AutorecoveringConnection.java:365)     在   com.rabbitmq.client.impl.recovery.AutorecoveringConnection.access $ 000(AutorecoveringConnection.java:48)     在   com.rabbitmq.client.impl.recovery.AutorecoveringConnection $ 1.shutdownCompleted(AutorecoveringConnection.java:345)     在   com.rabbitmq.client.impl.ShutdownNotifierComponent.notifyListeners(ShutdownNotifierComponent.java:75)     在   com.rabbitmq.client.impl.AMQConnection $ MainLoop.run(AMQConnection.java:572)     在java.lang.Thread.run(Thread.java:722)引起:   com.rabbitmq.client.AlreadyClosedException:连接已经存在   由于连接错误而关闭;原因:   com.rabbitmq.client.MissedHeartbeatException:缺少心跳   心跳= 45秒   com.rabbitmq.client.impl.AMQChannel.ensureIsOpen(AMQChannel.java:190)     在com.rabbitmq.client.impl.AMQChannel.rpc(AMQChannel.java:223)at   com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:209)     在   com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:118)     在com.rabbitmq.client.impl.ChannelN.queueDeclare(ChannelN.java:779)     在   com.rabbitmq.client.impl.recovery.AutorecoveringChannel.queueDeclare(AutorecoveringChannel.java:230)     在   com.rabbitmq.client.impl.recovery.RecordedQueue.recover(RecordedQueue.java:36)     在   com.rabbitmq.client.impl.recovery.AutorecoveringConnection.recoverQueues(AutorecoveringConnection.java:448)     ......还有7个

这是我非常简单的消费者代码。请注意,我在新线程中编写了所有代码,因为我不希望我的构造函数被阻塞。

private ConnectionFactory factory = null;
private Connection connection = null;
private Channel channel = null;

private PaymentInfoFromGlobalServerConsumer() {
    new Thread(new Runnable() {
        public void run() {
            factory = new ConnectionFactory();
            try {
                factory.setUri(amqpServerUrl);
                factory.setAutomaticRecoveryEnabled(true);
                factory.setNetworkRecoveryInterval(30000); // In case of broken connection, try again every 30 seconds (hope this is correct understanding)
                factory.setRequestedHeartbeat(45); //Keep sending the heartbeat every 45 seconds to prevent any routers from considering the connection stale.
            } catch (KeyManagementException | NoSuchAlgorithmException | URISyntaxException e) {
                //Will never happen if configured properly
                logger.error(e);
                return;
            }

            try {
                connection = factory.newConnection();
                channel = connection.createChannel();
                //Create a durable queue (if not already present)
                channel.queueDeclare(merchantId, true, false, false, null);

                QueueingConsumer consumer = new QueueingConsumer(channel);
                channel.basicConsume(merchantId, false, consumer);

                while (true) {
                    QueueingConsumer.Delivery delivery = consumer.nextDelivery();
                    String billId = new String(delivery.getBody());

                    //TODO - Redeliveries are possible as per design
                    System.out.println(" [x] Received '" + billId + "'");
                    System.out.println(" [x] Done" );

                    channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
                }               
            } catch (IOException | ConsumerCancelledException | InterruptedException e) {
                e.printStackTrace();
                logger.error(e);
            } catch (ShutdownSignalException e) {
                System.out.println(e.isInitiatedByApplication() + " " + e.isHardError());
            } finally {
                close();
            }
        }           
    }).start();
}

public void close() {
    try {
        if (channel != null) channel.close();
    } catch (IOException | AlreadyClosedException e) {
        //Cannot do anything now
    }
    try {
        if (connection != null) connection.close();
    } catch (IOException | AlreadyClosedException e) {
        //Cannot do anything now
    }
}

我是amqp的新手,所以任何帮助都表示赞赏。谢谢

1 个答案:

答案 0 :(得分:-1)

尝试恢复拓扑以及连接。

factory.setTopologyRecoveryEnabled(true);