官方示例中提到,要使用hint可以采用下面的方式开启:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withHints()
.withCaching()
.build(context);
}
}
但是我按照上面的配置后,hint不会生效,debug时不会进入到filteredByHint(),在执行完cache相关的类后直接返回。
因此,关掉cache使hint生效,即:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withHints()
.build(context);
}
}
此外,如果同时使用了基于区间的过滤,需要注意二者的顺序:
public class CustomLoadBalancerConfiguration {
@Bean
public ServiceInstanceListSupplier discoveryClientServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withDiscoveryClient()
.withZonePreference()
.withHints()
.build(context);
}
}
有个choose()
方法,返回时,调用了ServiceInstanceListSupplier
接口的default Flux
方法。> get(Request request)
在default Flux
方法里面调用了一个父类> get(Request request)
Supplier
的get()
方法
// ServiceInstanceListSupplier
default Flux<List<ServiceInstance>> get(Request request) {
return get();
}
而这个接口有好几个实现类,其中包括ZonePreferenceServiceInstanceListSupplier
,CachingServiceInstanceListSupplier
,HintBasedServiceInstanceListSupplier
这三个类:
withCaching()
会先进入CachingServiceInstanceListSupplier
类中,执行它的get()
方法,直接返回一个Flux
,然后直接进行response。>
// CachingServiceInstanceListSupplier
@Override
public Flux<List<ServiceInstance>> get() {
return serviceInstances;
}
withCaching()
则会调用HintBasedServiceInstanceListSupplier
的get()
方法,在HintBasedServiceInstanceListSupplier
中首先会调用ServiceInstanceListSupplier
的get(request)
方法(上面的get()方法)
// HintBasedServiceInstanceListSupplier
@Override
public Flux<List<ServiceInstance>> get(Request request) {
return delegate.get(request).map(instances -> filteredByHint(instances, getHint(request.getContext())));
}
这次get()
调用的实现类是ZonePreferenceServiceInstanceListSupplier
,在里面进行基于zone过滤
// ZonePreferenceServiceInstanceListSupplier
@Override
public Flux<List<ServiceInstance>> get() {
return getDelegate().get().map(this::filteredByZone);
}
总结:
choose(){
HintBasedServiceInstanceListSupplier.get(){
ZonePreferenceServiceInstanceListSupplier.getDelegate().get().map(this::filteredByZone);
}
}
消费者
server:
port: 8080
spring:
application:
name: consumer-01
cloud:
nacos:
server-addr: localhost:8848
loadbalancer:
ribbon:
enabled: false
enabled: true
configurations: zone-preference
zone: myzone
hint:
default: myhint
生产者
server:
port: 8081
spring:
application:
name: provider-01
cloud:
nacos:
server-addr: localhost:8848
discovery:
metadata:
zone: myzone
hint: myhint
loadbalancer:
ribbon:
enabled: false
enabled: true
configurations: zone-preference