Spring-amqp-QueueBuilder 应该保留对队列的引用而不是字符串名称

问题描述 投票:0回答:0

我有 2 个匿名队列。他们都设置了

___Declarables extends AbstractAmqpDeclarables
在启动时实例化为@Bean。

但是在启动时 - rabbitMQ 没有给队列一个名字,所以 2 个队列中的一个有 2 个绑定,另一个队列没有绑定。如果

QueueBuilder
持有对 queueObject 的引用而不是名称,则此对象创建可能会延迟到足以让 rabbitMQ 生成名称。

这是为 rabbitMQ 生成的名称,格式为

amq.gen-<random>
而不是 spring-amqp 生成的名称格式
spring.gen-<random>

编辑:如果我调用

QueueBuilder.durable();
而不是
QueueBuilder.durable(queueName);
生成的名称变为
spring.gen-<random>
而不是
amq.gen-<random>

最小可重现示例:

  1. 制作人
@Bean("amqpEmitterEventPublisherAdapter")
public EventPublisher<OurChangeEvent, Boolean> emitterEventsPublisherAdapter(
@Qualifier("amqpTemplate") RabbitTemplate rabbitTemplate
) {
final var publisher = new OurAmqpProducerImpl(rabbitTemplate);
return new OurEventAmqpPublisherAdapter(
    publisher,
    amqpConfigProps.getGlobalExchangeName(),
    ourEventsConfigProps.getOurEventsBindingPrefix(),
    ourEventsConfigProps.getOurEmitEventsBindingDataSuffix(),
    amqpConfigProps.isEnabled()
);
}
  1. Producer - 具有不同的后缀 - 一个新的绑定
@Bean("amqpEmitterEventPublisherAdapter2")
public EventPublisher<OurChangeEvent, Boolean> emitterEventsPublisherAdapter2(
@Qualifier("amqpTemplate") RabbitTemplate rabbitTemplate
) {
final var publisher = new OurAmqpProducerImpl(rabbitTemplate);
return new OurEventAmqpPublisherAdapter(
    publisher,
    amqpConfigProps.getGlobalExchangeName(),
    ourEventsConfigProps.getOurEventsBindingPrefix(),
    ourEventsConfigProps.getOurDifferentSuffix(),
    amqpConfigProps.isEnabled()
);
}
  1. Declarables——这就是问题所在。队列的名称是“”。好的,有 1 个可声明的。没有 2 个声明。
    @Bean("emitEventsDeclarables")
    public Declarables emitEventsDeclarables(
        @Qualifier("mainAmqpAdmin") RabbitAdmin admin,
        @Qualifier("GlobalAmqpExchange") Exchange exchange
    ) {
        final var bindingKey =
            ourEventsConfigProps.getOurEventsBindingPrefix() +
                ".*." +
                ourEventsConfigProps.getOurEmitEventsBindingDataSuffix();
        final var cfg = new OurEventsExclusiveDeclarables(
            exchange,
            ourEventsConfigProps.getOurEmitEventsQueueName(), //=""
            bindingKey,
            true
        );

        final var declarables = cfg.declarables();
        for (Declarable d : declarables.getDeclarables()) {
            d.setAdminsThatShouldDeclare(admin);
        }
        return declarables;
    }
  1. 可声明的队列名称也为“”
@Bean("emitEventsDeclarables2")
public Declarables emitEventsDeclarables2(
@Qualifier("mainAmqpAdmin") RabbitAdmin admin,
@Qualifier("GlobalAmqpExchange") Exchange exchange
) {
final var bindingKey =
    ourEventsConfigProps.getOurEventsBindingPrefix() +
        ".*." +
        ourEventsConfigProps.getOurEmitEventsBindingDataSuffix();
final var cfg = new OurDifferentExclusiveDeclarables(
    exchange,
    ourEventsConfigProps.getOurEmitEventsQueueName(), //=""
    bindingKey,
    true
);

final var declarables = cfg.declarables();
for (Declarable d : declarables.getDeclarables()) {
    d.setAdminsThatShouldDeclare(admin);
}
return declarables;
}

因此我们得到了 2 个具有匿名队列名称的声明。现在 Spring-amqp-QueryBuilder 变得困惑了:

public class OurEventsExclusiveDeclarables extends AbstractAmqpDeclarables {
    private final boolean isSingleActiveConsumer;

    public OurEventsExclusiveDeclarables(
        Exchange exchange,
        String queueName,
        String bindingKey,
        boolean isSingleActiveConsumer
    ) {
        this.exchange = exchange;
        this.queueName = queueName;
        this.bindingKey = bindingKey;
        this.isSingleActiveConsumer = isSingleActiveConsumer;
    }

    /** Exclusive queue with no name.
     * @return Declarables
     */
    @Override
    protected Declarables declarables() {
        QueueBuilder queueBuilder = 
 //Here is the problem - QueryBuilder is built too soon. RabbitMQ has not had time to generate a name
QueueBuilder.durable(queueName).exclusive();
//This will result in a spring generated name - not a RabbitMQ generated name
//QueueBuilder.durable().exclusive();
        System.out.println("binding queue name:" + queueName+ " to exchange:" + exchange.getName() + " with binding key:" + bindingKey);
        if (isSingleActiveConsumer) {
            queueBuilder.singleActiveConsumer();
        }
        final Queue queue = queueBuilder.build();
        final Binding binding = BindingBuilder.bind(queue).to(exchange).with(bindingKey).noargs();
        return new Declarables(queue, binding);
    }
}
spring rabbitmq amqp spring-amqp
© www.soinside.com 2019 - 2024. All rights reserved.