rabbitmq异步消息确认机制

rabbitMq在实际发消息的时候会把 nextPublishSeqNo 存入到 unconfirmedSet 中

// com.rabbitmq.client.impl.ChannelN#basicPublish()
public void basicPublish(String exchange, String routingKey,
                         boolean mandatory, boolean immediate,
                         BasicProperties props, byte[] body)
    throws IOException
{
    // 只有当开启消息确认和事务消息时,才会在初始时设置 nextPublishSeqNo=1
    if (nextPublishSeqNo > 0) {
        unconfirmedSet.add(getNextPublishSeqNo());
        nextPublishSeqNo++;
    }
    if (props == null) {
        props = MessageProperties.MINIMAL_BASIC;
    }
    AMQCommand command = new AMQCommand(
        new Basic.Publish.Builder()
            .exchange(exchange)
            .routingKey(routingKey)
            .mandatory(mandatory)
            .immediate(immediate)
            .build(), props, body);
    try {
        transmit(command);
    } catch (IOException e) {
        metricsCollector.basicPublishFailure(this, e);
        throw e;
    }
    metricsCollector.basicPublish(this);
}

在消息回调时处理seqNo

// com.rabbitmq.client.impl.ChannelN#handleAckNack()
private void handleAckNack(long seqNo, boolean multiple, boolean nack) {
    if (multiple) {
        // 如果是批量的,则把当前seqNo以及之前的全部清除
        unconfirmedSet.headSet(seqNo + 1).clear();
    } else {
        unconfirmedSet.remove(seqNo);
    }
    synchronized (unconfirmedSet) {
        onlyAcksReceived = onlyAcksReceived && !nack;
        if (unconfirmedSet.isEmpty())
            unconfirmedSet.notifyAll();
    }
}

nextPublishSeqNo 不会被发送到 rabbitMq 。如何保证与 deliveryTag 对应?在一个连接存续期间,服务器返回的 deliveryTag 会自增,需要应用程序自己保证每发一条信息自增1,与服务器保持一致。

非确认消息,不会使用到 nextPublishSeqNo 。

为了保证能及时的响应异步回调,驱动程序会启动一个线程专门监听rabbitMq服务消息。

// com.rabbitmq.client.impl.AMQConnection.MainLoop
private class MainLoop implements Runnable {

    /**
     * Channel reader thread main loop. Reads a frame, and if it is
     * not a heartbeat frame, dispatches it to the channel it refers to.
     * Continues running until the "running" flag is set false by
     * shutdown().
     */
    @Override
    public void run() {
        boolean shouldDoFinalShutdown = true;
        try {
            while (_running) {
                Frame frame = _frameHandler.readFrame();
                // 循环读取来自服务器的消息
                readFrame(frame);
            }
        } catch (Throwable ex) {
            if (ex instanceof InterruptedException) {
                // loop has been interrupted during shutdown,
                // no need to do it again
                shouldDoFinalShutdown = false;
            } else {
                handleFailure(ex);
            }
        } finally {
            if (shouldDoFinalShutdown) {
                doFinalShutdown();
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值