磁盘空间不足会导致RabbitMQ丢失消息而不是阻止连接

时间:2013-06-02 12:07:33

标签: java rabbitmq blocking diskspace

我有一个java应用程序,它将消息发布到RabbitMQ服务器 当可用磁盘空间低于兔子的低水印时,我会遇到意外行为。

预期的行为是the connection will become blocking,使我的应用程序挂起了对Channel.basicPublish的调用。

实际行为是管理控制台中的连接似乎是阻塞,但是Channel.basicPublish的调用返回时没有错误,应该发布的消息丢失。
这种行为破坏了RabbitMQ最重要的特性,即强健性。

以下是我的测试应用程序的最小版本。它所做的就是每秒使用递增索引(1,2,3,...)发布消息。 RabbitMQ服务器接收到的消息很好,直到我将低水位设置为一个非常高的值,方法是将以下行放在rabbitmq.config文件中:

[    
  {rabbit, [{disk_free_limit, 60000000000}]}
].

重新启动服务器后,我在管理控制台中收到磁盘空间不足通知,连接被标记为“阻塞”,服务器不再收到任何消息。但是,应用程序会继续运行并发送消息,就像没有任何错误一样。当我将水印减少回正常值时,服务器再次收到消息,但是在连接阻塞时发送的所有消息都将丢失。

  • 我做错了吗?
  • 这是RabbitMQ中的错误吗?
  • 如果有,是否有解决方法?

操作系统:Windows 8 64位
RabbitMQ服务器版本:3.1.1
RabbitMQ Java客户端版本:3.1.0

测试应用程序代码:

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;

public class Main {

    private final static Logger logger = LoggerFactory.getLogger(Main.class);
    private final static String QUEUE_NAME = "testQueue";

    private static Channel channel = null;

    private static void connectToRabbitMQ() throws IOException {
        ConnectionFactory factory = new ConnectionFactory();
        Connection connection = factory.newConnection();
        channel = connection.createChannel();
        channel.queueDeclare(
                QUEUE_NAME,
                true,       // Durable - survive a server restart
                false,      // Not exclusive to this connection
                false,      // Do not autodelete when no longer in use
                null        // Arguments
        );
    }

    private static void disposeChannel()
    {
        if (channel == null) {
            return;
        }
        try {
            channel.close();
        } catch (Exception e) {
        } finally {
            channel = null;
        }
    }

    public static void main(String[] args) throws Exception {

        boolean interrupted = false;
        int messageNumber = 1;

        while (!interrupted) {
            byte[] message = Integer.toString(messageNumber).getBytes();
            try {
                if (channel == null) {
                    connectToRabbitMQ();
                }
                channel.basicPublish(
                        "",
                        QUEUE_NAME,
                        MessageProperties.MINIMAL_PERSISTENT_BASIC,
                        message
                );
                logger.info("Published message number {}", messageNumber);
                messageNumber++;
            } catch (Exception e) {
                logger.info("Unable to connect to RabbitMQ...");
                disposeChannel();
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                logger.info("Interrupted");
                interrupted = true;
            }
        }
    }
}

0 个答案:

没有答案