You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Make DelegatingServiceInstanceListSupplier implement SelectedInstanceCallback #1221
I've tried to setup a custom load balancer as described in this post. However, with spring-cloud-starter-loadbalancer:3.1.4 I'm experiencing
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier' available: more than one 'primary' bean found among candidates: [CustomServiceInstanceListSupplier, retryAwareDiscoveryClientServiceInstanceListSupplier]
@Configuration
@LoadBalancerClient(value = "custom", configuration = CustomLoadBalancerConfiguration.class)
public class CustomLoadBalancerClient {
}
public class CustomLoadBalancerConfiguration {
@Bean
@Primary
public ServiceInstanceListSupplier customServiceInstanceListSupplier(ConfigurableApplicationContext context, RedissonClient redissonClient) {
ServiceInstanceListSupplier delegate = ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withCaching()
.build(context);
return new CustomServiceInstanceListSupplier(delegate, redissonClient);
}
}
public class CustomServiceInstanceListSupplier extends DelegatingServiceInstanceListSupplier implements SelectedInstanceCallback {
...
}
When deploying the application to Kubernetes along spring-cloud-kubernetes-facric8-loadbalancer:2.1.4 and activating spring.cloud.kubernetes.loadbalancer.mode=SERVICE it's even getting worse
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier' available: more than one 'primary' bean found among candidates: [customServiceInstanceListSupplier, kubernetesServicesListSupplier, retryAwareDiscoveryClientServiceInstanceListSupplier]
Am I doing something wrong, or is the example from the post wrong?
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier' available: expected single matching bean but found 2: customServiceInstanceListSupplier,kubernetesServicesListSupplier
Further debugging revealed a second issue. My CustomServiceInstanceListSupplier implements SelectedInstanceCallback which the RoundRobinLoadBalancer respects by calling SelectedInstanceCallback#selectedServiceInstance
However, with Spring retry on the classpath my CustomServiceInstanceListSupplier is wrapped in a RetryAwareServiceInstanceListSupplier which is not respecting SelectedInstanceCallback on its delegate.
@Configuration(proxyBeanMethods = false)
@ConditionalOnBlockingDiscoveryEnabled
@ConditionalOnClass(RetryTemplate.class)
@Conditional(BlockingOnAvoidPreviousInstanceAndRetryEnabledCondition.class)
@AutoConfigureAfter(BlockingSupportConfiguration.class)
@ConditionalOnBean(ServiceInstanceListSupplier.class)
public static class BlockingRetryConfiguration {
@Bean
@ConditionalOnBean(DiscoveryClient.class)
@Primary
public ServiceInstanceListSupplier retryAwareDiscoveryClientServiceInstanceListSupplier(
ServiceInstanceListSupplier delegate) {
return new RetryAwareServiceInstanceListSupplier(delegate);
}
}
I suspect that every implementation of ServiceInstanceListSupplier using some sort of "delegate" has the same problem, see RequestBasedStickySessionServiceInstanceListSupplier as an example.
@OlgaMaciaszek any feedback appreciated as I'm stuck here. What I need to achieve is that my own ServiceInstanceListSupplier is used regardless of any auto-configured supplier. Or I need a way to use the auto-configured one as a delegate in my supplier, but that won't work as retryAwareDiscoveryClientServiceInstanceListSupplier is marked @Primary.
@spencergibb Can you please have a look and give me hint if this is considered a bug or if any configuration possibility exists as a workaround? I've tried using @AutoConfigureAfter(LoadBalancerClientConfiguration.ReactiveRetryConfiguration.class) at my class annotated with @LoadBalancerClient without a chance. retryAwareDiscoveryClientServiceInstanceListSupplier is still configured after mine ...
Hello, @HJK181. This is happening as for retrying failed requests, RetryAwareServiceInstanceListSupplier is enabled by default. As indicated in the docs, if you do not want it to be instantiated, you should set spring.cloud.loadbalancer.retry.avoidPreviousInstance to false. Does this solve your issue?
changed the title [-]Custom configuration for the LoadBalancer doesn't work[/-][+]Make DelegatingServiceInstanceListSupplier implement SelectedInstanceCallback[/+]on Jul 28, 2023
Activity
HJK181 commentedon Mar 27, 2023
Removing
@Primaryleads toHJK181 commentedon Mar 28, 2023
Further debugging revealed a second issue. My
CustomServiceInstanceListSupplierimplementsSelectedInstanceCallbackwhich theRoundRobinLoadBalancerrespects by callingSelectedInstanceCallback#selectedServiceInstanceHowever, with Spring retry on the classpath my
CustomServiceInstanceListSupplieris wrapped in aRetryAwareServiceInstanceListSupplierwhich is not respectingSelectedInstanceCallbackon its delegate.I suspect that every implementation of
ServiceInstanceListSupplierusing some sort of "delegate" has the same problem, seeRequestBasedStickySessionServiceInstanceListSupplieras an example.HJK181 commentedon Mar 31, 2023
@OlgaMaciaszek any feedback appreciated as I'm stuck here. What I need to achieve is that my own
ServiceInstanceListSupplieris used regardless of any auto-configured supplier. Or I need a way to use the auto-configured one as a delegate in my supplier, but that won't work asretryAwareDiscoveryClientServiceInstanceListSupplieris marked@Primary.HJK181 commentedon Apr 12, 2023
@spencergibb Can you please have a look and give me hint if this is considered a bug or if any configuration possibility exists as a workaround? I've tried using
@AutoConfigureAfter(LoadBalancerClientConfiguration.ReactiveRetryConfiguration.class)at my class annotated with@LoadBalancerClientwithout a chance.retryAwareDiscoveryClientServiceInstanceListSupplieris still configured after mine ...OlgaMaciaszek commentedon Apr 12, 2023
Hello, @HJK181. This is happening as for retrying failed requests,
RetryAwareServiceInstanceListSupplieris enabled by default. As indicated in the docs, if you do not want it to be instantiated, you should setspring.cloud.loadbalancer.retry.avoidPreviousInstancetofalse. Does this solve your issue?HJK181 commentedon Apr 12, 2023
I’d like to use the retry functionality, but in conjunction with my custom instance list supplier.
OlgaMaciaszek commentedon Apr 12, 2023
That property does not disable retry. It only disables the
RetryAwareServiceInstanceListSupplierthat handles avoiding retrying on the same instance.16 remaining items
HJK181 commentedon Apr 13, 2023
I can check tomorrow if I find the time to setup my IDE for contributing to the project. Is there any chance that it will be backported to 3.1.x?
OlgaMaciaszek commentedon Apr 13, 2023
Unfortunately, not really. We mostly only backport bugfixes. This would be a new feature.
Fix DelegatingServiceInstanceListSupplier must
HJK181 commentedon Apr 19, 2023
@OlgaMaciaszek #1226 FYI
[-]Custom configuration for the LoadBalancer doesn't work[/-][+]Make DelegatingServiceInstanceListSupplier implement SelectedInstanceCallback[/+]