我有 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>
最小可重现示例:
@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()
);
}
@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()
);
}
@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;
}
@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);
}
}