Spring Cloud Gateway + Nacos 实现服务上下线无缝切换

这篇具有很好参考价值的文章主要介绍了Spring Cloud Gateway + Nacos 实现服务上下线无缝切换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

大家好,我是不才陈某~

最近知识星球的球友在学习星球中的《精尽Spring Cloud Alibaba》专栏提到一个问题,相信也有很多人在线上环境遇到过,或许也因此被批过:一个集群中有某个服务突然下线,但是网关还是会去请求这个实例,所以线上就报错了,报错信息如下图:

Spring Cloud Gateway + Nacos 实现服务上下线无缝切换,java,spring cloud,开发语言,spring,后端

究其原因到底为何呢?有没有一种靠谱的解决方案呢?别着急,往下看

产生原因

Gateway中有个缓存 CachingRouteLocator ,而网关服务使用的是lb模式,服务在上线或者下线之后,未能及时刷新这个缓存,相应的源码如下:

public class CachingRouteLocator implements Ordered, RouteLocator,
  ApplicationListener<RefreshRoutesEvent>, ApplicationEventPublisherAware {

 private static final Log log = LogFactory.getLog(CachingRouteLocator.class);

 private static final String CACHE_KEY = "routes";

 private final RouteLocator delegate;

 private final Flux<Route> routes;

 private final Map<String, List> cache = new ConcurrentHashMap<>();

 private ApplicationEventPublisher applicationEventPublisher;

 public CachingRouteLocator(RouteLocator delegate) {
  this.delegate = delegate;
  routes = CacheFlux.lookup(cache, CACHE_KEY, Route.class)
    .onCacheMissResume(this::fetch);
 }

 private Flux<Route> fetch() {
  return this.delegate.getRoutes().sort(AnnotationAwareOrderComparator.INSTANCE);
 }

 @Override
 public Flux<Route> getRoutes() {
  return this.routes;
 }

 /**
  * Clears the routes cache.
  * @return routes flux
  */
 public Flux<Route> refresh() {
  this.cache.clear();
  return this.routes;
 }

 @Override
 public void onApplicationEvent(RefreshRoutesEvent event) {
  try {
   fetch().collect(Collectors.toList()).subscribe(list -> Flux.fromIterable(list)
     .materialize().collect(Collectors.toList()).subscribe(signals -> {
      applicationEventPublisher
        .publishEvent(new RefreshRoutesResultEvent(this));
      cache.put(CACHE_KEY, signals);
     }, throwable -> handleRefreshError(throwable)));
  }
  catch (Throwable e) {
   handleRefreshError(e);
  }
 }

 private void handleRefreshError(Throwable throwable) {
  if (log.isErrorEnabled()) {
   log.error("Refresh routes error !!!", throwable);
  }
  applicationEventPublisher
    .publishEvent(new RefreshRoutesResultEvent(this, throwable));
 }

 @Deprecated
 /* for testing */ void handleRefresh() {
  refresh();
 }

 @Override
 public int getOrder() {
  return 0;
 }

 @Override
 public void setApplicationEventPublisher(
   ApplicationEventPublisher applicationEventPublisher) {
  this.applicationEventPublisher = applicationEventPublisher;
 }
}

那么解决方案就自然能够想出来,只需要在服务下线时能够去实时的刷新这个缓存自然就解决了

解决方案

这里通过去监听 Nacos 实例刷新事件,一旦出现实例发生变化马上删除缓存。在删除负载均衡缓存后,Spring Cloud Gateway 在处理请求时发现没有缓存会重新拉取一遍服务列表,这样之后都是用的是最新的服务列表了,也就达到了我们动态感知上下线的目的。

代码如下:

@Component
@Slf4j
public  class NacosInstancesChangeEventListener extends Subscriber<InstancesChangeEvent> {
    @Resource
    private CacheManager defaultLoadBalancerCacheManager;

    @Override
    public void onEvent(InstancesChangeEvent event) {
        log.info("Spring Gateway 接收实例刷新事件:{}, 开始刷新缓存", JacksonUtils.toJson(event));
        Cache cache = defaultLoadBalancerCacheManager.getCache(SERVICE_INSTANCE_CACHE_NAME);
        if (cache != null) {
            cache.evict(event.getServiceName());
        }
        log.info("Spring Gateway 实例刷新完成");
    }

    @Override
    public Class<? extends com.alibaba.nacos.common.notify.Event> subscribeType() {
        return InstancesChangeEvent.class;
    }
}

这里通过继承的方式监听 Nacos 的 InstancesChangeEvent,在 onEvent 接收到实例刷新的信息后直接删除对应服务的负载均衡缓存,缓存的名字是定义在 Spring Gateway 的相关代码中的,直接引入即可,Cache 则是继承自 Spring Cache 接口,负载均衡缓存也继承了 Cache 接口,有了 Cache 接口就可以直接使用其接口定义的 evict 方法即可,而缓存的 key 名就则就是服务名,在 InstancesChangeEvent 中,通过 getServiceName 就可以得到服务名。

这里就不演示了,有兴趣的小伙伴可以测试一下

最后说一句(别白嫖,求关注)

陈某每一篇文章都是精心输出,如果这篇文章对你有所帮助,或者有所启发的话,帮忙点赞、在看、转发、收藏,你的支持就是我坚持下去的最大动力!

另外陈某的知识星球开通了,公众号回复关键词:知识星球 获取限量30元优惠券加入只需89元,一顿饭钱,但是星球回馈的价值却是巨大,目前更新了Spring全家桶实战系列、亿级数据分库分表实战、DDD微服务实战专栏、我要进大厂、Spring,Mybatis等框架源码、架构实战22讲等....每增加一个专栏价格将上涨20元

Spring Cloud Gateway + Nacos 实现服务上下线无缝切换,java,spring cloud,开发语言,spring,后端

关注公众号:【码猿技术专栏】,公众号内有超赞的粉丝福利,回复:加群,可以加入技术讨论群,和大家一起讨论技术,吹牛逼!文章来源地址https://www.toymoban.com/news/detail-617700.html

到了这里,关于Spring Cloud Gateway + Nacos 实现服务上下线无缝切换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Cloud微服务架构:实现分布式系统的无缝协作

    🎉欢迎来到架构设计专栏~Spring Cloud微服务架构:实现分布式系统的无缝协作 ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹 ✨博客主页:IT·陈寒的博客 🎈该系列文章专栏:架构设计 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习 🍹文章作者技术和水

    2024年02月08日
    浏览(61)
  • Spring Cloud 2022.x版本使用gateway和nacos实现动态路由和负载均衡

    Spring Cloud Alibaba官方:https://sca.aliyun.com/zh-cn/ Spring Cloud官网:https://spring.io/projects/spring-cloud Spring Cloud与Spring Cloud Alibaba版本对应说明:https://sca.aliyun.com/zh-cn/docs/2022.0.0.0/overview/version-explain 下载地址:https://github.com/alibaba/nacos/releases 下载编译压缩并解压:nacos-server-2.2.3.zip。 1.1、

    2024年02月11日
    浏览(41)
  • Spring Cloud Gateway + Nacos 灰度发布

    本文将会使用 SpringCloud Gateway 网关组件配合 Nacos 实现 灰度发布(金丝雀发布) 创建子模块 服务提供者  provider ,网关模块  gateway 父项目 pom.xml 配置 服务提供者 provider 这里我们计划引入  nacos , 所以先创建一个 nacos 配置文件  dataId  为  provider.properties , 这里用默认的命名

    2024年02月03日
    浏览(36)
  • 大规模 Spring Cloud 微服务无损上下线探索与实践

    🎉欢迎来到云原生技术应用专栏~大规模 Spring Cloud 微服务无损上下线探索与实践 ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹 ✨博客主页:IT·陈寒的博客 🎈该系列文章专栏:云计算技术应用 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习 云计算技术

    2024年02月09日
    浏览(39)
  • Spring Cloud集成Nacos实现服务配置中心 | Spring Cloud 7

    先我们来看一下,微服务架构下关于配置文件的一些问题: 配置文件相对分散。在一个微服务架构下,配置文件会随着微服务的增多变的越来越多,而且分散在各个微服务中,不好统一配置和管理。 配置文件无法区分环境,开发环境、测试环境、线上环境。微服务项目可能会

    2024年02月14日
    浏览(56)
  • Spring Cloud Gateway集成Nacos作为注册中心和配置中心

    本篇文章将介绍Spring Cloud Alibaba体系下Spring Cloud Gateway的搭建,服务注册中心和分布式配置中心使用Nacos,后续将会持续更新,介绍集成Sentinel,如何做日志链路追踪,如何做全链路灰度发布设计,以及Spring Cloud Gateway的扩展等。 ​ Spring Boot,Spring Cloud,Discovery,Config等基础依

    2024年02月11日
    浏览(113)
  • 【SpringCloud】11、Spring Cloud Gateway使用Sentinel实现服务限流

    1、关于 Sentinel Sentinel 是阿里巴巴开源的一个流量防卫防护组件,可以为微服务架构提供强大的流量防卫能力,包括流量控制、熔断降级等功能。Spring Cloud Gateway 与 Sentinel 结合,可以实现强大的限流功能。 Sentinel 具有以下特性: 丰富的应用场景:Sentinel 承接了阿里巴巴近

    2024年02月01日
    浏览(57)
  • spring cloud整合spring boot,整合nacos、gateway、open-feign等组件

    想看具体详情的可以看我的github链接:codeking01/platform-parent: spring cloud整合spring boot、nacos、gateway、open feign等组件 (github.com) 由于我升级了jdk17,所以用上了spring boot 3.0.2了。 踩坑无数,一堆无用文章,写来写去,本文主要是提供给有基础的开发者再次快速搭建使用(确定版本

    2024年02月11日
    浏览(59)
  • Spring Cloud Gateway集成Swagger实现微服务接口文档统一管理及登录访问

    本文将介绍如何在 Spring Cloud 微服务中使用 Swagger 网关来统一管理所有微服务的接口文档,并通过 Spring Security 实现登录后才能访问 Swagger 文档,以确保接口数据的安全访问。 在开始之前,需要假设你已经完成了 Spring Cloud Gateway 的相关配置,并且已经了解了基本的网关配置知

    2024年02月05日
    浏览(44)
  • Spring Cloud Gateway 网关整合 Knife4j 4.3 实现微服务接口文档聚合

    🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🌺 仓库主页: Gitee 💫 Github 💫 GitCode 💖 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请纠正! youlai-mall 开源微服务商城新版本基于 Spring Boot 3 和 Java 17,同时采用 Knife4j 4.3。与以前版本不同的是

    2024年02月05日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包