我有一个从RabbitMQ读取并写入我的数据库的消费者。我使用的Consumer类是用户定义的,它实现了Callable。
手动消费者方法:
public static void consume(Queue queue, String consumerName, int threadCount, int prefetchCount) throws Exception {
DbUtil.initializeConnectionPool();
Connection connection = RabbitMqUtils.getConnection();
Channel channel = connection.createChannel();
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicQos(threadCount * prefetchCount);
queue.initiateConsumer(channel, consumer);
System.out.println("MQ Server: " + connection.getAddress() + ":" + connection.getPort());
System.out.println("Queue: " + queue.name);
// Multi-threading code.
threadPool = Executors.newFixedThreadPool(threadCount);
Class c = Class.forName(consumerName);
while (true) {
Consumer consumerInstance = (Consumer) c.newInstance();
java.sql.Connection dbConnection = null;
QueueingConsumer.Delivery delivery = null;
try {
delivery = consumer.nextDelivery();
dbConnection = DbUtil.getConnectionFromPool();
consumerInstance.setConsumerDetails(new String(delivery.getBody()), dbConnection, channel, queue, delivery);
threadPool.submit(consumerInstance);
} catch (Exception e) {
if (delivery != null) {
Consumer.reQueueMessage(delivery, new String(delivery.getBody()), channel, queue, e);
}
if (dbConnection != null) {
dbConnection.close();
}
}
}
}
通话方式:
@Override
public Object call() throws Exception {
try {
doWork(this.message, this.dbConnection);
channel.basicAck(this.delivery.getEnvelope().getDeliveryTag(), false);
} catch (Exception e) {
Consumer.dumpMsg(e.getMessage(), "Error Msg");
Consumer.reQueueMessage(this.delivery, new String(this.delivery.getBody()), this.channel, this.queue, e);
} finally {
java.sql.Connection dbConnection = this.dbConnection;
if (dbConnection != null) {
dbConnection.close();
}
}
return null;
}
doWork
是我在Consumer
班级的孩子中重写的方法。问题是大约1000条消息中的1条卡在unacked
状态的队列中。我只能通过停止然后启动消费者来使它们脱离unacked
状态。我的猜测是网络流量中的确认丢失了。我想知道是否有一种方法可以使消息在返回队列之前暂时保持在unacked
状态,以便重新使用。