关于微服务平滑发布机制,LoadBalancer与nacos和openfeign的那些事

背景:

当我们更新微服务时,停止服务,然后再启动服务,这个时间内,服务是不可用的,但是nacos并不能立马感知到我们的微服务已经下线了,nacos是定时轮询当前的服务是否健康,当检测到服务不健康时,会移除当前服务,这个时间可以再nacos中进行设置检查时间,但是无论怎么设置,都会存在这种服务不可用的状态,尤其再访问高时。

解决方案:

服务滚动发布,当微服务下线时,使用钩子ShutdownHook函数来通知nacos下线。

 具体实现:

首先当我们请求我们的网关时,网关会选择一个服务实例进行转发,那他这个实例是从哪里来的呢,这个关乎到我们的版本,我们使用的是springcloud alibaba 、openfeign,spingcloud已经自己研制了负载均衡组件,loadbalancer,这个loadbalancer目前有两种默认的负载均衡算法分别是

RandomLoadBalancer、
RoundRobinLoadBalancer

他们都实现了

ReactorServiceInstanceLoadBalancer接口,包括nacos也实现了这个接口
NacosLoadBalancer。关于这几个负载均衡器可自行了解

我们今天聊一下他的原理

首先,是从网关转发,网关根据自己的设置去找微服务实例,这个设置会判定是走本地缓存还是走实时读取nacos上的实例,如果是缓存,那么就存在服务下线延迟的问题,因为他需要根据时间去调度来更新缓存。所以我们的解决方案是,当我们服务下线时,将本地缓存清理,然后让服务去nacos上拉取最新的实例列表,这样就可以实现服务下线,也不会导致服务不可用的问题。

@Slf4j
@Component
public class ServiceChangeNotifier extends Subscriber<InstancesChangeEvent> {

    @Autowired
    private ApplicationContext context;

    @PostConstruct
    public void init() {
        // 注册当前自定义的订阅者以获取通知
        NotifyCenter.registerSubscriber(this);
    }

    @Override
    public void onEvent(InstancesChangeEvent event) {
        String serviceName = event.getServiceName();
        if (serviceName.contains(":")) {
            return;
        }
        String split = Constants.SERVICE_INFO_SPLITER;
        if (serviceName.contains(split)) {
            serviceName = serviceName.substring(serviceName.indexOf(split) + split.length());
        }
        log.info("服务上下线: {}", serviceName);
        ObjectProvider<LoadBalancerCacheManager> cacheManagerProvider = context.getBeanProvider(LoadBalancerCacheManager.class);
        Cache cache = cacheManagerProvider.getIfAvailable().getCache(CachingServiceInstanceListSupplier.SERVICE_INSTANCE_CACHE_NAME);
        if (cache != null) {
            boolean present = cache.evictIfPresent(serviceName);
            log.info("本地缓存处理结果:{}",present);
        }
    }

    @Override
    public Class<? extends Event> subscribeType() {
        return InstancesChangeEvent.class;
    }

}
NotifyCenter这个类,在初始化时,会将服务注册到nacos服务端,并且会触发关闭钩子(关键),具体看代码

这样,我们监听到nacos发布通知,然后直接执行本地缓存清理,即可完成缓存内的服务实例进行实时更新,完结。

最近更新

  1. TCP协议是安全的吗?

    2024-05-11 11:36:06       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-11 11:36:06       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-11 11:36:06       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-11 11:36:06       20 阅读

热门阅读

  1. 【贪心算法】Leetcode 134. 加油站【中等】

    2024-05-11 11:36:06       9 阅读
  2. Unity构建详解(12)——自动构建

    2024-05-11 11:36:06       12 阅读
  3. AlmaLinux 文件重命名 mv命令用法示例

    2024-05-11 11:36:06       10 阅读
  4. pnpm包管理工具的理解

    2024-05-11 11:36:06       5 阅读
  5. 根据地址栏url上key获取值

    2024-05-11 11:36:06       10 阅读
  6. JVM进程缓存 Caffeine

    2024-05-11 11:36:06       8 阅读