Spring Cloud 版本:

Dalston.SR5

今天使用Zuul发现一个和动态刷新相关的问题,动态刷新使用的是 /bus/refresh,即我的Zuul连着一个Rabbitmq,我这里是使用的总线刷新的方式,普通的刷新/refresh应该也是可以再现这个坑的。

我一共有两个服务,服务名分别为one和all,刷新之前的路由规则:

zuul:
ribbonIsolationStrategy: THREAD
retryable: true
add-host-header: true
servlet-path: /zuul/*
prefix: /test
routes:
#规则
n1:
path: /*
serviceId: all

改为:

zuul:
ribbonIsolationStrategy: THREAD
retryable: true
add-host-header: true
servlet-path: /zuul/*
prefix: /test
routes:
#规则
n0:
path: /one
serviceId: one
n1:
path: /*
serviceId: all

加了个n0的规则,并且放在了n1前边,按说刷新之后,如果访问/test/one,那么应该会由服务【one】来处理,而非服务【all】,结果却是仍然会交由服务【all】来处理。

很坑是不是,我觉得这是个BUG,目前我还没有研究源码,但是通过实验得出了几个结论,并且也有了一个不用修改源码的解决方案,详情如下:

先说结论:

通过动态刷新的配置,对于路由规则的变动,只能新增和修改,不能删除;并且新增的规则在匹配顺序上,位于老规则的后边,也就是说,一旦你老规则里配置了个/*,那么后边的新规则你怎么改都不能生效,仍然会路由到/*对应的服务上。

再说解决办法:

借助上边描述的规则,我们可以将配置规则换一种写法再刷新进去,新的写法如下:

zuul:
ribbonIsolationStrategy: THREAD
retryable: true
add-host-header: true
servlet-path: /zuul/*
prefix: /test
routes:
#规则
n1:
path: /one
serviceId: one
n2:
path: /*
serviceId: all

这里修改了n1,然后新增了n2,巧妙的借助这个规则完成了,让/one路由到服务【one】上,其他规则还继续让服务【all】来处理。

这中解决方式,感觉还是不完美,后续我们可以通过修改源码,或者关注社区的方式,纠正这个坑(BUG)。

————————————————————2018年5月15日 追加——————————————————————————

经过调查发现:

zuul获取路由规则的时候,会从所有路由规则中选择第一个能正则匹配的,用来处理当前的请求,接着,我们需要看看刷新之后配置的顺序是不是有问题。

这里看到顺序是按照配置文件的顺序进行加载,应该是没有问题的,结果发现配置文件的顺序并不能保证。这里我们先不去管为什么顺序不能保证了,因为需要牵扯大量的refresh端点事件、配置中心相关代码。

这里根据我们的需求直接决定改成优先精确匹配,精确匹配失败再正则匹配即可,修改后:

修改非常简单,重在调查问题的过程。

如果你想调查配置中心相关代码,这里给个思路,或许有所帮助:

调用/bus/refresh时候走了这段。

继续跟进代码。

属性对比的完整截图,两个Map,一个是之前的配置内容,一个是修改后的配置内容,最终结果是对比得出的两者的不同点。

广播了属性替换事件,具体广播的处理者在哪又得跟源码了,时间有限,就写到这里吧。欢迎指正和补充

----------------------------------------------------------2018年7月31日 ----------------------------------------------------------------

今天又发现一个新的坑,也是和上文同一个原因所致。

之前的结论:

通过动态刷新的配置,对于路由规则的变动,只能新增和修改,不能删除;并且新增的规则在匹配顺序上,位于老规则的后边,也就是说,一旦你老规则里配置了个/*,那么后边的新规则你怎么改都不能生效,仍然会路由到/*对应的服务上。

现在发现同一个路由规则的变动也是适用的,也就是说,如果你之前配了一个路由规则:

zuul:
routes:
route1:
path: /a/**
url: http://URL/PATH/

将所有/a/xxx的请求交给下边这个url处理,之后你通过配刷新的方式改为了:

zuul:
routes:
route1:
path: /a/**
serviceId: service1

是没有效果的,所有/a/xxx的请求还是会被之前那个url处理。

正确的姿势是改为:

zuul:
routes:
route1:
path: /a/**
serviceId: service1
url:

再刷新配置。

总结一下原因:

1、配置刷新目前存在问题无法删除已有的路由规则,只能修改已有规则和新增规则。

2、在路由的serviceId和url同时存在的时候,会以url为准,只有url为空的时候才会交给serviceId来处理。

该问题在

Edgware.SR3

版本中,仍然未得到解决。也许我该转向spring cloud gateway了

完毕

Spring Cloud Zuul的一个坑的更多相关文章

  1. Spring Cloud Zuul 中文文件上传乱码

    原文地址:https://segmentfault.com/a/1190000011650034 1 描述 使用Spring Cloud Zuul进行路由转发时候吗,文件上传会造成中文乱码“?”.1. ...

  2. Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式。

    时间过的很快,写springcloud(十):服务网关zuul初级篇还在半年前,现在已经是2018年了,我们继续探讨Zuul更高级的使用方式. 上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制 ...

  3. 笔记:Spring Cloud Zuul 快速入门

    Spring Cloud Zuul 实现了路由规则与实例的维护问题,通过 Spring Cloud Eureka 进行整合,将自身注册为 Eureka 服务治理下的应用,同时从 Eureka 中获取了 ...

  4. Spring Cloud Zuul 限流详解(附源码)(转)

    在高并发的应用中,限流往往是一个绕不开的话题.本文详细探讨在Spring Cloud中如何实现限流. 在 Zuul 上实现限流是个不错的选择,只需要编写一个过滤器就可以了,关键在于如何实现限流的算法. ...

  5. spring cloud zuul参数调优

    zuul 内置参数 zuul.host.maxTotalConnections 适用于ApacheHttpClient,如果是okhttp无效.每个服务的http客户端连接池最大连接,默认是200. ...

  6. Spring Cloud Zuul 网关使用与 OAuth2.0 认证授权服务

    API 网关的出现的原因是微服务架构的出现,不同的微服务一般会有不同的服务地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题: 客户端会 ...

  7. spring cloud: zuul(四): 正则表达式匹配其他微服务(给其他微服务加版本号)

    spring cloud: zuul(四): 正则表达式匹配其他微服务(给其他微服务加版本号) 比如我原来有,spring-boot-user微服务,后台进行迭代更新,另外其了一个微服务: sprin ...

  8. Spring Cloud Zuul 快速入门

    Spring Cloud Zuul 实现了路由规则与实例的维护问题,通过 Spring Cloud Eureka 进行整合,将自身注册为 Eureka 服务治理下的应用,同时从 Eureka 中获取了 ...

  9. Spring cloud Zuul网关异常处理

    Spring cloud Zuul网关异常处理 一 异常测试: 1> 创建一个pre类型的过滤器,并在该过滤器的run方法实现中抛出一个异常.比如下面的实现,在run方法中调用的doSometh ...

随机推荐

  1. JavaScript:Math 对象

    ylbtech-JavaScript:Math 对象 Math 对象用于执行数学任务. 使用 Math 的属性和方法的语法: var pi_value=Math.PI; var sqrt_value= ...

  2. maven-assembly-plugin 入门指南

    当你使用 Maven 对项目打包时,你需要了解以下 3 个打包 plugin,它们分别是 plugin function maven-jar-plugin maven 默认打包插件,用来创建 proj ...

  3. LeetCode295-Find Median from Data Stream && 480. 滑动窗口中位数

    中位数是有序列表中间的数.如果列表长度是偶数,中位数则是中间两个数的平均值. 例如, [2,3,4] 的中位数是 3 [2,3] 的中位数是 (2 + 3) / 2 = 2.5 设计一个支持以下两种操 ...

  4. iOS开发-Reachability实时检测Wifi,2G/3G/4G/网络状态

    最近遇到一个功能就是根据用户当前的网络状,用户未联网需要提示一下,如果是Wifi可以推荐一些图片新闻,如果是3G模式设置为无图的模式,获取网络状态比较简单,毕竟中国现在的流量还是一个比较贵的状态,哪天 ...

  5. centos6.8 mysql5.6.34 root密码重置

    1.关闭正在运行的MySQL service mysql stop 2.启动MySQL的安全模式 mysqld_safe --skip-grant-tables 等1分钟如果还没返回的话,新开shel ...

  6. Python3 比较两个图片是否类似或相同

    Python代码 #coding:utf8 import os from PIL import Image,ImageDraw,ImageFile import numpy import pytess ...

  7. Google Guava新手教程

         以下资料整理自网络 一.Google Guava入门介绍 引言 Guavaproject包括了若干被Google的 Java项目广泛依赖 的核心库,比如:集合 [collections] . ...

  8. QuickXDev插件自己主动升级后player no exist

      昨晚上QuickXDev插件执行还ok,今天打开电脑启动sublime text2后.右键run with player提示player no exist watermark/2/text/aHR ...

  9. 使用checkstyle来规范你的项目

    Checkstyle是什么 自从做了程序员,关于格式化的讨论就不曾中断过,到底什么才是正确的,什么才是错误的,到现在也没有完整的定论.但随着时间发展,渐渐衍生出一套规范出来.没有什么绝对的正确和错误, ...

  10. 我们为何放弃Eclipse,投奔IntelliJ IDEA

    本文来源于我在InfoQ中文站原创的文章,原文地址是:http://www.infoq.com/cn/news/2013/11/why-drop-eclipse-use-intellij Nikita ...