-
Notifications
You must be signed in to change notification settings - Fork 41.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MeterBinder beans that directly or indirectly depend on MeterRegistry beans cause a cycle #30636
Comments
There has always been a cycle if you inject a |
I understand that the dependency was earlier.
Сan you give an example of how to restructure? I see the problem in the fact that class RabbitConnectionFactoryMetricsPostProcessor implements BeanPostProcessor, Ordered {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof AbstractConnectionFactory) {
bindConnectionFactoryToRegistry(getMeterRegistry(), beanName, (AbstractConnectionFactory) bean);
}
return bean;
}
private MeterRegistry getMeterRegistry() {
if (this.meterRegistry == null) {
this.meterRegistry = this.context.getBean(MeterRegistry.class);
}
return this.meterRegistry;
} this leads to a call to the class MeterRegistryPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof MeterRegistry) {
getConfigurer().configure((MeterRegistry) bean);
}
return bean;
} and in this method there is an appeal to void configure(MeterRegistry registry) {
...
if (!this.hasCompositeMeterRegistry || registry instanceof CompositeMeterRegistry) {
addBinders(registry); // <--- throw here
}
} And then an error occurs, This makes it impossible to use |
Unfortunately, I don't think there's anything we can do about that without regressing #12855. Why does your |
We have a lot of services that use In such an application of |
A small comment about the problem #12855.
It seems to me that the example is not quite correct. @Bean
Exchange configure(RabbitAdmin rabbitAdmin) {
Exchange topicExchange = ExchangeBuilder.topicExchange(EXCHANGE_NAME).build();
rabbitAdmin.declareExchange(topicExchange);
Queue queue = QueueBuilder.durable(QUEUE_NAME).build();
rabbitAdmin.declareQueue(queue);
rabbitAdmin.declareBinding(BindingBuilder.bind(queue).to(topicExchange).with(ROUTING_KEY).noargs());
return topicExchange;
} RabbitMQ initialization can be redone according to the documentation Spring AMQP: @Bean
Exchange topicExchange() {
return ExchangeBuilder.topicExchange(EXCHANGE_NAME).build();
}
@Bean
Queue queue() {
return QueueBuilder.durable(QUEUE_NAME).build();
}
@Bean
Binding binding(Queue queue, Exchange topicExchange) {
return BindingBuilder.bind(queue).to(topicExchange).with(ROUTING_KEY).noargs();
} In this case, the example will work correctly:
If incorrect usage is not encouraged, then @AllArgsConstructor
public class RabbitMetricsInitializing implements MeterBinder {
private final Map<String, ? extends AbstractConnectionFactory> factories;
@Override
public void bindTo(MeterRegistry registry) {
factories.forEach((name, factory) -> bindConnectionFactoryToRegistry(registry, name, factory));
}
} Thank you for your attention, I will no longer distract you with my reasoning. |
We may be able to improve the situation by using |
It turns out that we can't use Stepping back a bit, the issue is probably broader than Rabbit and will apply to any I've pushed some prototype code here but it could do with a review. |
I'm a bit concerned that the prototype may swing things too far in the other direction. With the proposed changes in place, I think I'd find it hard to explain why we have support for The more I think about this, the more it reminds me of the problems we had with |
@wilkinsona Hi, I'm also faced with the problem while dealing with rabbitmq metrics, could you please explain how to work around this problem? Running with Spring Boot v2.7.1, Spring v5.3.21
MeterRegistry bean is autowired into my configuration to bind meter registry into rabbitmq connectionfactory
|
Boot will automatically configure metrics for the Rabbit connection factory of each |
@wilkinsona I've added an exclude in the application class, but the problem is still there. Maybe we had the cycle before, because I've got this error after I've upgraded from spring boot 2.3 to 2.7 where as you say any cyclic dependencies are prohibited by default. |
Without the post-processor in place, I'm struggling to think of what could be creating the cycle. Can you share some code that reproduces the problem? |
This comment was marked as outdated.
This comment was marked as outdated.
Ah, I'd missed that you weren't already using a |
@wilkinsona Actually, MeterBinder didn't work here, but my metrics were shown up on /metrics when I created a customizer bean
Could you explain in two words, when MeterBinder is needed? |
Maybe 200…
In what way didn't it work? Same problem with a cycle or something else? |
Sorry, man. Meter binder was autowired, but when I call /metrics, there are no any rabbit mq metrics. Method bindTo of a meter binder wasn't executed. |
I was hit by the very similar problem while using Spring Boot 2.6.12 with Spring Cloud 2021.0.3. I was able to narrow down the cyclic dependency problem to occur only with configuration classes from Spring Boot ecosystem:
What helped in my case was resigning from RabbitMQ health indicator by setting following property:
This basically removes rabbitHealthContributor bean. Maybe it will help the others. |
I think #33070 has addressed this concern. Implementing We're going to try deferring the meter binding in 3.0. |
@wilkinsona For those not able to upgrade to 3.x yet, can you please advise how to workaround this issue in 2.7? I'm encountering this issue with a setup like so:
Is the guidance to use |
|
That seems to have done the trick. Thank you, @wilkinsona. |
Hi, after upgrading Spring Boot from 2.1 to 2.6, I have a problem (project sample)
Spring Boot version: 2.6.6
Spring dependency:
Problem
I can't use
MeterBinder
in a service that is injected with something that depends on theConnectionFactory
.Example of a problematic service:
Workaround
As a workaround, you can use the annotation
@Lazy
:But it doesn't seem to me that main stream.
The text was updated successfully, but these errors were encountered: