RabbitMQ中的交易消费

时间:2017-08-01 12:53:36

标签: java rabbitmq jms mom

我还是 RabbitMQ 的新手。我需要一个MOM系统用于这些目的:

  1. 在我的逻辑执行之前消耗已发布的消息 成功。
  2. 经纪人不必从中删除已发布的消息 排队直到我的逻辑成功执行。
  3. 对于这些目标,我在第一次尝试时编写了以下代码:

        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        final Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);
        boolean autoAck = false;
        channel.basicConsume(QUEUE_NAME, autoAck, "ProcessorOneTag",
                new DefaultConsumer(channel)
                {
                    @Override
                    public void handleDelivery(String consumerTag,
                                               Envelope envelope,
                                               AMQP.BasicProperties properties,
                                               byte[] body)throws IOException
                    {
                        try
                        {
                            channel.txSelect();
                            String routingKey = envelope.getRoutingKey();
                            String contentType = properties.getContentType();
                            long deliveryTag = envelope.getDeliveryTag();
                            System.out.println("Recieve Message is :" + new String(body));
                            int reslt = //execute my logic   
                            if(result == 0)
                                channel.txCommit();
                            else
                                channel.txRollback();
                        }
                        catch(Throwable t)
                        {
                            t.printStackTrace();
                        }
                    }
                });
    

    通过这种方法,我实现了第二个目的,换句话说,经纪人没有删除我的消息,但有一次队列中的所有消息都被消耗掉了,并且所有消息都被回滚,经纪人没有这样做。 t再次向我的消费者发送消息。

    在第二次尝试时,我编写了以下代码:

        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        final Channel channel = connection.createChannel();
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);
        boolean autoAck = false;
        channel.basicConsume(QUEUE_NAME, autoAck, "ProcessorOneTag",
                new DefaultConsumer(channel)
                {
                    @Override
                    public void handleDelivery(String consumerTag,
                                               Envelope envelope,
                                               AMQP.BasicProperties properties,
                                               byte[] body)throws IOException
                    {
                        try
                        {
                            String routingKey = envelope.getRoutingKey();
                            String contentType = properties.getContentType();
                            long deliveryTag = envelope.getDeliveryTag();
                            System.out.println("Recieve Message is :" + new String(body));
                            int reslt = //execute my logic   
                            if(result == 0)
                                channel.basicAck(deliveryTag, false);
                            else
                                channel.basicNack(deliveryTag,false,true);
                        }
                        catch(Throwable t)
                        {
                            t.printStackTrace();
                        }
                    }
                });
    

    通过这个解决方案,我达到了两个目标,但我不知道我的代码是否正确?该方法是否会导致高TPS的生产环境出现问题?我不知道 basicNack 方法的重新排队标志是重还是轻?

1 个答案:

答案 0 :(得分:0)

几个月前我有同样的要求。我经历了很多解决方案,这对我有用。

我将交货标签存储在内存中的某处,如果我的逻辑顺利,我会手动确认消息或拒绝该消息。我为此目的使用了以下方法。

if (success)
connectionModel.BasicAck(Convert.ToUInt64(uTag), false);
else
connectionModel.BasicReject(Convert.ToUInt64(uTag), true);

以上代码在我的生产中运行良好,速度为5000毫秒/秒。好吧, basicNack 方法给我带来了问题。