[英]basicAck does not remove message from broker - RabbitMQ
I'm doing following flow in my application: 我在我的应用程序中执行以下操作:
get 1 message from broker(manual acknowledge) 从经纪人那里得到1条消息(手动确认)
do some processing 做一些处理
start transaction on database and broker 在数据库和代理上启动事务
insert some records in database and publish some messages on broker(different queue) 在数据库中插入一些记录并在代理上发布一些消息(不同的队列)
commit database and broker 提交数据库和代理
ack message that you got from broker in step 1. 您在步骤1中从经纪人处获得的确认消息。
All operation on broker is done via a single channel. 经纪人的所有操作都是通过单一渠道完成的。 here is the preparation code: 这是准备代码:
Connection brokerConnection = factory.newConnection();
Channel channel = brokerConnection.createChannel();
channel.basicQos(1);
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume("receive-queue", false, consumer);
Following is my code. 以下是我的代码。 I have removed try
, catch
parts to make it clear. 我已经删除了try
, catch
部分以使其清楚。 I log all exceptions to file. 我将所有例外记录到文件中。 Step 1: 步骤1:
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
Request request = (Request) SerializationUtils.deserialize(delivery.getBody());
Step 2, 3, 4, 5: 第2,3,4,5步:
dbConnection.setAutoCommit(false);
channel.txSelect();
stmt = dbConnection.prepareStatement(query);
/* set paramteres */
stmt.executeUpdate();
channel.basicPublish(/* exchange name */, "KEY", MessageProperties.PERSISTENT_BASIC, /* result */ result);
dbConnection.commit();
channel.txCommit();
dbConnection.setAutoCommit(true);
Step 6: 第6步:
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
After one iteration I can see records in database and broker(means it is working fine until step 5). 在一次迭代之后,我可以在数据库和代理中看到记录(意味着它在第5步之前正常工作)。 The problem is the message on receive queue is not removed after step 6 and management plug-in shows one un-acked message. 问题是在步骤6之后未删除接收队列上的消息,并且管理插件显示一条未确认的消息。 Also I don't see any exception in log file. 此外,我在日志文件中看不到任何异常。 Can anyone help? 有人可以帮忙吗?
[UPDATE1] [UPDATE1]
Now I create one channel for publishing and another channel for receiving. 现在我创建一个用于发布的频道和另一个用于接收的频道。 This is working now. 现在正在运作。 So how to use a single channel for receiving and publishing(with transactions)? 那么如何使用单一渠道进行接收和发布(使用交易)? I have used a single channel for receiving and publishing before but that was without transactions. 我之前使用过单个频道进行接收和发布,但没有交易。
[UPDATE2] [UPDATE2]
I moved step 6 inside transaction and it is working now. 我在事务中移动了第6步,它现在正在运行。
dbConnection.setAutoCommit(false);
channel.txSelect();
stmt = dbConnection.prepareStatement(query);
/* set paramteres */
stmt.executeUpdate();
channel.basicPublish(/* exchange name */, "KEY", MessageProperties.PERSISTENT_BASIC, /* result */ result);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
dbConnection.commit();
channel.txCommit();
dbConnection.setAutoCommit(true);
I'm a bit confused. 我有点困惑。 I just want the publish section to be inside transaction. 我只是希望发布部分在内部事务中。
You've put the channel in transactional mode - and acks are transactional things. 您已将频道置于事务模式 - 而ack是事务性事物。 So you either need to consume and ack on a separate non-transactional channel, or else just accept that your ack needs to come before the tx.commit. 所以你需要在一个单独的非交易渠道上消费和确认,或者只是接受你的ack需要在tx.commit之前。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.