基于dubbo2.7.4.1的标签路由功能实现

1,571 阅读7分钟

升级的背景:

        最近项目组在做dubbo版本的升级工作,由于之前的项目dubbo版本基本上是2.6,版本相对来说比较老,同时要使用2.7版本之后的标签路由功能,所以就做了dubbo版本的升级工作,以及标签路由功能的调研,下面和大家分享一下dubbo升级,以及标签路由功能的实现。   

dubbo2.7简介:

dubbo.apache.org/zh-cn/blog/…

官方提供的升级文档:

dubbo.apache.org/zh-cn/docs/…

        现在的项目基本上都是dubbo停止更新的版本,之后dubbo项目重启,dubbo经历了很多的优化,解决了很多之前版本的问题,而且之后想要实现项目的灰度发布等功能,基于上述的需求点,同时考虑dubbo的稳定性等,经过调研后选择了2.7.4.1这个版本,这个版本提供了标签路由,以及很好的项目兼容性,同时它也是dubbo官方推荐的可以部署到生产环境的稳定版本。

  一  dubbo版本的升级

        由于本次的升级涉及到公司基本上所有的系统,同时现阶段公司一些老项目仍然是springmvc的版本,只有后续开发的项目都是springboot版本,下面先介绍一下,springmvc版本的dubbo版本升级。

  1. Spring MVC 升级2.7.4.1版本dubbo

       dubbo版本的升级主要是升级两个关键的地方,其一就是dubbo版本版本的升级,其二由于公司的注册中心是zookpeer,并且之前实用的zkclient,升级到2.7版本之后需要升级curator,如果不升级项目启动会报错。

<dependency>    <groupId>org.apache.dubbo</groupId>    <artifactId>dubbo</artifactId>    <version>2.7.4.1</version></dependency>

      如果系统中使用的为zkclient则将其替换为curator。旧版的zkclient由于和dubbo2.7.4.1版本不兼容启动会报错,如果系统中使用的就是curator链接的ZK则忽略这一步。如果系统中使用了hadoop为了防止冲突还需要将 curator手动排除。

<dependency>    <groupId>org.apache.curator</groupId>    <artifactId>curator-recipes</artifactId>    <version>4.2.0</version>    <exclusions>        <exclusion>            <groupId>org.apache.zookeeper</groupId>            <artifactId>zookeeper</artifactId>        </exclusion>    </exclusions></dependency>

       升级完版本等信息,还需要修改项目的dubbo配置文件,dubbo配置文件里的client改为curator,dubbo.registry.client=curator,同时由于dubbo项目已经是Apache的开源项目,所以需要修改dubbo配置文件的头部信息。

        做完这些工作之后重新刷新maven,就可以把改旧版dubbo的相关引用类修改为新的,引入新版本的dubbo类。

2.Springboot  升级2.7.4.1版本dubbo

boot 版本的dubbo升级基本上和mvc版本大同小异,可以说是更简单一些,同样是升级dubbo的版本,以及zookeeper连接jar,因为公司的项目引入相关的jar各不相同,所以这里只介绍关键的jar信息。

(一)jar版本升级

注意:如果依赖了 sentinel 的话,需要修改 sentinel 相关依赖的 jar 包,由

<dependency>    <groupId>com.alibaba.csp</groupId>    <artifactId>sentinel-dubbo-adapter</artifactId></dependency>

改为

<dependency>    <groupId>com.alibaba.csp</groupId>    <artifactId>sentinel-apache-dubbo-adapter</artifactId>    <version>1.7.1</version></dependency>

(2)刷新maven修改旧版dubbo的相关引用类

         dubbo中提供了许多字符串和集合相关的方法,如果系统中用到了则需要将其改为其他包下的对应工具类。

(3) dubbo 配置修改,各个项目不太一样

这里引用的是zkclient需要修改 curator,否则启动报错:Caused by: java.lang.IllegalStateException: No such extension org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter by name zkclient

提示:升级了2.7.4.1版本之后项目的配置文件可以不再配置client:curator,因为底层源码默认用curator作为zookeeper的连接客户端,感兴趣的可以看看源码。

       升级到新的dubbo版本之后,项目的启动正常,服务能够正常对外提供服务。

二  dubbo标签路由的使用

    在一个调用链非常长的功能中,如果想修改其中的一个特性,并进行测试,而又不影响该环境的其他用户使用现有功能、特性,例如:

       1. A、B、C、D之间通过Dubbo实现远程调用

       2. 这些模块可能有一个或者多个实例 

       3. 此环境由多个人员(包括开发、测试)同时使用

      此时若想修改B中的某个功能,增加一个特性(称为FAT1),并且也注册到此环境中,则会发生如下问题:当其他的用户从使用此功能时,从A发起的调用可能会由于Dubbo带的负载均衡算法等原因,在带有FAT1和不带有FAT1的实例间来回切换,最后的表现可能就是某一个功能使用两次,产生的结果竟然不一样!

       解决这个问题最简单的方法就是给每个功能特性(FAT)独立设置一个测试环境,例如这一期有20个功能特性上线,就部署20个环境好了。。。。等等,是不是哪里不对?部署20个环境?你是否感觉到你BOSS站在你座位后面,随时准备把你扔出办公室?

      仔细分析这个问题,要解决的重点有两个:

     1. 将不同人员进行开发/测试的特性隔离开。

     2. 不修改的部分尽量共享,以节省资源。

     综上,最好的解决方案应该是如下图所示:

       1. 建立一个Baseline环境,该环境包含了应用程序所需的所有组件、数据集等。

       2. 对于不同的功能特性,为该特性修改的组件独立发布一个实例,称之为一个Feature,对应的测试场称之为FAT+编号,例如Feature 1的测试环境称为FAT1。

       3. 开发和测试某个功能特性(例如Feature 1)时,利用路由功能让上游模块自动选择正确的下游模块,便于开发人员调试以及测试人员查看效果 。

       通过对Dubbo文档的探索(dubbo.apache.org/zh-cn/docs/…),发现实现此功能的方案有如下几种:

     1. 使用条件路由规则

     2. 使用动态标签功能

     3. 使用静态标签功能

       经过对上述三种方法的分析,发现各自的优缺点如下:

      1. 如果使用条件路由:

       优点是需求明晰,如果我想设计一个FAT测试场,其中A、B是待测试组件,可以使用路由规则host != A => host !=B和host = A => host = B

     缺点是:

      A. 需要使用Dubbo控制台修改路由规则,对于一般的开发/测试来说,权限太大了。

      B. 如果组件A、B、D同时修改了,当请求从A->B->C传递时,C不一定知道这个请求是否应该传到D,使用条件路由无法实现。

      2. 如果使用动态标签,1中的问题B能够得到解决,因为标签在整个调用链路中都会以Attachment的形式被传递,但是A问题依然无法解决

     综上,要实现此功能,最好是使用3. 静态标签功能,根据官方文档,Dubbo的标签路由功能是2.7开始才可用的,所以我们需要使用这个版本。

**     1  服务端的设置**

      服务端的设置非常简单,只需在配置文件中添加dubbo.provider.tag和dubbo.consumer.tag属性,客户端请求时必须携带与服务端对应的tag才能进行访问。

#服务端携带的
tagdubbo.provider.tag=old
#是否强制使用tag,默认false
request.tag.force=false

#客户端携带tagdubbo.consumer.tag=old

 **   2 客户端****的设置**

客户端在请求时需在URL上添加你想要访问的tag,如果访问的tag不存在并且 request.tag.force=false 则会降级访问到tag为空的服务。

  (1)读取配置文件的tag

    配置文件信息

dubbo.consumer.group=test
#服务端携带的tag
dubbo.provider.tag=old
#是否强制使用tag,默认false
request.tag.force=false
#客户端携带tag
dubbo.consumer.tag=old

读取tag号的工具类(也可以在nacos中进行配置)

@Componentpublic class DubboTagConfiguration {    
   @Value("${dubbo.consumer.tag}")   
   private String dubboConsumerTag;   
   public String getDubboConsumerTag() {        
     return dubboConsumerTag;    
 }}

  (2) 在dubbo的Filter中添加请求的tag号

     经过测试通过对项目的tag设置,在集群环境下能够实现我们项目所需要的功能,由于项目还没有正式上线,所以后续有什么问题还会及时更新出来,希望感兴趣的同学可以一起探讨。