spring-cloud-alibaba
spring-cloud-alibaba copied to clipboard
是否提供ribbon基于事件机制的ServerListUpdater
使用feign调用服务时,ribbon默认使用PollingServerListUpdater定时任务更新服务,eureka有对应的EurekaNotificationServerListUpdater基于事件的更新,目前nacos是否有提供对应的基于事件的ServerListUpdater,可以更快的感知到服务的上下线。
welcome to contribute it!
这个功能确实很急需啊
is there any progress?
如果仅仅基于Ribbon,可以自行扩展,可以参考https://gitee.com/nepxion/Discovery/blob/6.x.x/discovery-plugin-register-center/discovery-plugin-register-center-starter-nacos/src/main/java/com/nepxion/discovery/plugin/registercenter/nacos/decorator/NacosServerListDecorator.java
getUpdatedListOfServers上触发出一个事件即可,仅供参考
最终我基于namingService subscribe
API重写了ServerListUpdater
接口,基本实现基于事件机制的ServerListUpdater
,但是在实测中发现,nacos的事件推送很不稳定,在服务节点下线后基本需要5-10秒以后client才能收到NamingEvent
,作为事件订阅本身来讲,这个延迟是否可以接受?是否还有优化空间?
顺着eventListener的源码往上扒了扒,发现Nacos的事件订阅实际上是基于pull模式的“伪订阅”…,然后去阿里云看了一下MSE的服务下线优势…大概明白为啥Eureka有基于事件监听机制的ServerListUpdater而Nacos没有了…
最终我基于
namingService subscribe
API重写了ServerListUpdater
接口,基本实现基于事件机制的ServerListUpdater
,但是在实测中发现,nacos的事件推送很不稳定,在服务节点下线后基本需要5-10秒以后client才能收到NamingEvent
,作为事件订阅本身来讲,这个延迟是否可以接受?是否还有优化空间?顺着eventListener的源码往上扒了扒,发现Nacos的事件订阅实际上是基于pull模式的“伪订阅”…,然后去阿里云看了一下MSE的服务下线优势…大概明白为啥Eureka有基于事件监听机制的ServerListUpdater而Nacos没有了…
您好,可以麻烦您提供下基于事件机制的ServerListUpdater的源码吗?谢谢。
监听器实现参考
/**
* @author: ruansheng
* @date: 2022-08-08
*/
@RequiredArgsConstructor
public class NacosInstancesChangeNotifier extends Subscriber<InstancesChangeEvent> implements SmartInitializingSingleton {
private final SpringClientFactory springClientFactory;
private final String applicationName;
@Override
public void onEvent(InstancesChangeEvent event) {
ILoadBalancer loadBalancer = this.springClientFactory.getLoadBalancer(event.getServiceName());
if (this.applicationName.equals(event.getServiceName()) || !(loadBalancer instanceof DynamicServerListLoadBalancer)) {
return;
}
((DynamicServerListLoadBalancer<?>) loadBalancer).updateListOfServers();
}
@Override
public Class<? extends Event> subscribeType() {
return InstancesChangeEvent.class;
}
@Override
public void afterSingletonsInstantiated() {
NotifyCenter.registerSubscriber(this);
}
}
定义监听器
@Bean
public NacosInstancesChangeNotifier nacosInstancesChangeNotifier(SpringClientFactory springClientFactory, Environment environment) {
String applicationName = environment.getProperty("spring.application.name", "");
return new NacosInstancesChangeNotifier(springClientFactory, applicationName);
}
监听器实现参考
/** * @author: ruansheng * @date: 2022-08-08 */ @RequiredArgsConstructor public class NacosInstancesChangeNotifier extends Subscriber<InstancesChangeEvent> implements SmartInitializingSingleton { private final SpringClientFactory springClientFactory; private final String applicationName; @Override public void onEvent(InstancesChangeEvent event) { ILoadBalancer loadBalancer = this.springClientFactory.getLoadBalancer(event.getServiceName()); if (this.applicationName.equals(event.getServiceName()) || !(loadBalancer instanceof DynamicServerListLoadBalancer)) { return; } ((DynamicServerListLoadBalancer<?>) loadBalancer).updateListOfServers(); } @Override public Class<? extends Event> subscribeType() { return InstancesChangeEvent.class; } @Override public void afterSingletonsInstantiated() { NotifyCenter.registerSubscriber(this); } }
定义监听器
@Bean public NacosInstancesChangeNotifier nacosInstancesChangeNotifier(SpringClientFactory springClientFactory, Environment environment) { String applicationName = environment.getProperty("spring.application.name", ""); return new NacosInstancesChangeNotifier(springClientFactory, applicationName); }
nacos的事件推送是不稳定的, 所以这样也不能很好的解决
@zhaoxilingcheng 长期的使用验证下来,nacos 的推送事件稳定性还是很高的。
当然,还可以同时配合其他机制来进一步保证稳定性,例如:当前服务实例下线时,基于消息订阅等相关方式将当前下线的实例通知给其他服务,然后其他服务将“下线的服务实例”缓存到当前服务的“黑名单”中,然后在负载均衡选择实例的时候跳过“黑名单”中的实例即可。