当前位置: 首页 > news >正文

springcloud loadbalancer nacos无损发布

前言

  • 故事背景
    jenkins部署时总是会有几秒钟接口调用报错,观察日志是因为流量被下发到已下线的服务,重启脚本在停止应用之前先调用nacos注销实例api后再重启依然会短暂出现此问题。项目架构是springcloud alibaba,通过openfeign进行微服务之间调用,猜测是LoadBalancer缓存问题。
  • 依赖版本
<dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2021.0.1.0</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.6.3</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>2021.0.1</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><exclusions><exclusion><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>3.1.1</version></dependency>
</dependencies>
  • loadbalancer配置
spring:cloud:loadbalancer:#需要引入Spring Retry依赖retry:enabled: true

springcloud loadbalancer缓存原理

  1. 启用启动首先装配Caffeine一级缓存,缓存应用实例,降低注册中心负载,提升性能
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述
    从上图可以看出,可以通过设置spring.cloud.loadbalancer.cache来关闭一级缓存,其值默认是开启的。

  2. feign初次从loadbalance获取应用实例会触发装配ServiceInstanceListSupplier逻辑
    在这里插入图片描述
    在这里插入图片描述

从一级缓存中获取应用实例:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

解决方案

通过上面的源码分析,根本原因是应用从nacos下线后,loadbalancer的一级缓存未移除下线实例,有以下解决办法:

  1. 重启脚本下线nacos实例后,等待一级缓存失效后(默认35s)再重启应用
  2. 禁用一级缓存(不建议)
  3. 监听nacos下线事件,手动移除实例

方案实现

  • 采用方案
    监听nacos下线事件,手动移除实例
  • 代码实现
    • 思路
      nacos订阅需要删除缓存的服务名(serviceName),下线应用主动调用nacos实例注销api后由nacos server触发自定义的订阅回调逻辑
    • nacos订阅源码分析
      在这里插入图片描述在这里插入图片描述

从上图可以看出默认只会订阅当前服务名,这也是为什么以下代码在其他应用主动下线后没有触发回调的原因
在这里插入图片描述
- 编写指定服务nacos订阅与删除实例缓存逻辑

package com.xxx.xxx.feign.listener;import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import lombok.SneakyThrows;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.Cache;
import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheManager;
import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheProperties;
import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
import org.springframework.context.annotation.Configuration;import javax.annotation.Resource;
import java.util.Arrays;/*** @description nacos应用监听* @date 2024/7/29*/
@Configuration
@ConditionalOnProperty(name = "spring.cloud.loadbalancer.cache.enabled", havingValue = "true")
@AutoConfigureAfter(LoadBalancerCacheProperties.class)
public class NacosInstanceListener implements InitializingBean {@Resourceprivate NacosServiceManager nacosServiceManager;@Resourceprivate NacosDiscoveryProperties properties;@Resourceprivate LoadBalancerCacheManager caffeineLoadBalancerCacheManager;@Override@SneakyThrowspublic void afterPropertiesSet() {NamingService namingService = nacosServiceManager.getNamingService(properties.getNacosProperties());namingService.subscribe("xxx-product-xxx", properties.getGroup(), Arrays.asList(properties.getClusterName()), event -> {if (event instanceof NamingEvent) {NamingEvent namingEvent = (NamingEvent) event;String svrName = namingEvent.getServiceName();Cache cache = caffeineLoadBalancerCacheManager.getCache(CachingServiceInstanceListSupplier.SERVICE_INSTANCE_CACHE_NAME);if (cache != null) {cache.evict(svrName);}System.out.println(event);}});}
}
  • 下线服务主动调用nacos注销实例接口,观察效果
    在这里插入图片描述

在这里插入图片描述

从上图可以看到,删除服务实例缓存回调成功触发,考虑到调用nacos api下线到上述代码被成功执行的耗时,应用重启脚本最好在调用nacos api成功后等待1秒左右再停止服务。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【数据结构】线段树
  • 临床数据科学中如何用R来进行缺失值的处理(上)
  • 24/8/6算法笔记 不同核函数
  • 读友好的缓存淘汰算法
  • Go语言依赖管理:如何配置和恢复Go模块镜像
  • 【python】Linux升级版本
  • python 装饰器记录函数用时
  • stm32应用、项目
  • RNN循环网络层
  • PostgreSQL(二十五)PG_FDW的使用
  • SpringMVC快速学习
  • C#裁剪图像的几种方法总结
  • 关于使用Next遇到的一些新特性
  • 【C++】STL | vector 详解及重要函数的实现
  • 工作随记:我在OL8.8部署oracle rac遇到的问题
  • 【Leetcode】104. 二叉树的最大深度
  • CSS相对定位
  • Cumulo 的 ClojureScript 模块已经成型
  • input的行数自动增减
  • learning koa2.x
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • vue的全局变量和全局拦截请求器
  • 开源SQL-on-Hadoop系统一览
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 如何利用MongoDB打造TOP榜小程序
  • 为什么要用IPython/Jupyter?
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • Nginx实现动静分离
  • ​520就是要宠粉,你的心头书我买单
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • # 移动硬盘误操作制作为启动盘数据恢复问题
  • #if #elif #endif
  • (¥1011)-(一千零一拾一元整)输出
  • (02)vite环境变量配置
  • (2022 CVPR) Unbiased Teacher v2
  • (9)STL算法之逆转旋转
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (二)延时任务篇——通过redis的key监听,实现延迟任务实战
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (六)软件测试分工
  • (四)stm32之通信协议
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • .NET WPF 抖动动画
  • .net 发送邮件
  • .NET 漏洞分析 | 某ERP系统存在SQL注入
  • .net 生成二级域名
  • .NET 依赖注入和配置系统
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • .pop ----remove 删除
  • @DependsOn:解析 Spring 中的依赖关系之艺术
  • @Transactional类内部访问失效原因详解
  • [ solr入门 ] - 利用solrJ进行检索