dubbo怎么实现灰度发布?dubbo实现灰度发布方法

Dubb是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和Spring框架无缝集成。那dubbo怎么实现灰度发布?下面来我们就来给大家讲解一下。

dubbo怎么实现灰度发布.png

Dubbo的服务调用原理图:

dubbo怎么实现灰度发布?dubbo实现灰度发布方法.png

客户端在发起RPC服务调用之前,在客户端首先从服务器列表中选择一个服务调用者,包含如下关键角色:

1、Directory

服务的动态发现,通常基于注册中心进行服务的动态注册与发现,其具体实现类为RegistryDirectory。

2、Router

路由实现,其含义是根据Directory发现的所有服务提供者列表中,进行路由选择,也就是根据一定的路由规则选择合适的服务提供者,为Directory发现的服务提供者列表子集,可以基于Condition或脚本(默认为JS脚本,其实现类为ScriptRouter)。

3、LoadBalance

负载均衡机制,其作用主要是根据负载均衡算法(随机、轮询)等算法,从(Directory-->Router)中返回的服务提供者列表中选择一个服务提供者,进行本次的RPC服务调用。

4、Cluster

集群(容错机制),就是当从服务提供者列表中按照负载均衡算法选择一个服务提供者,进行RPC服务调用后,发送了异常后的策略,例如failover(重试)、failfast(快速失败)等。

服务的灰度发布,其目标是希望根据请求,某些请求走新版本服务器,某些请求走旧版本服务器,其本质就是路由机制,即通过一定的条件来缩小服务的服务提供者列表,正好与Dubbo的Router相吻合。

方案具体实现示例

本示例代码需要完成的任务是,对DemoService#createUser服务,其用户机构ID(orgId)为1的走新版本(当前服务提取者列表的最后一台服务器),其他的请求走所有的服务器(除最后一台服务器)。

1.png

2.png

由于是需要基于请求参数,本文给出基于JS脚本的路由机制,首先,当前版本的dubbo-admin可以后台页面维护基于条件表达式的路由规则,其界面如下:

3.png

4.png

备注:并且当前dubbo-admin版本,并不支持基于JS表达式的路由规则,如果手动建立基于表达式的路由规则,其页面将无法列出路由表达式,其界面如下:

5.png

JS脚本

各个项目,各个服务需要根据自身的需求,定义如下脚本:

1
 /**
  2 * DemoService router,针对不同的方法,可能需要各自提供,主要是参数的获取,不同的过滤规则
  3 * 针对参数进行路由过滤
  4 * 
  5 * 本示例针对 DemoSerivce# ResponseResult createUser(User user) 方法,根据user的orgId进行路由选择
  6 * @param invokers
  7 * @param invocation
  8 * @param context
  9 * @returns
 10 */
 11
 function demoService_createUser_router(invokers, invocation, context)
 {
     12
     if (invokers == null || invokers.size() < 1)
     {
         13
         return invokers;
         14
     }
     15
     16
     if (!"createUser".equals(invocation.getMethodName()))
     { // 如果方法不匹配,默认无条件通过该路由规则
         17
         return invokers;
         18
     }
     19
     20
     var availableInvokers = new java.util.ArrayList(invokers.size());
     21
     for (var i = 0; i < invokers.size(); i++)
     { // 先选择可用的服务提供者列表
         22
         if (invokers.get(i)
             .isAvailable())
         {
             23 availableInvokers.add(invokers.get(i));
             24
         }
         25
     }
     26
     27
     var invArguments = invocation.getArguments();
     28
     if (invArguments == null || invArguments.length == 0)
     { // 如果参数为空,无法根据参数进行路由选择
         29
         return availableInvokers;
         30
     }
     31
     32 // 获取需要进行路由的参数,这里使用第一个参数 ,这里各自根据各自的业务 进行获取,本实例默认使用第一个参数
     33
     var firstArgument = invArguments[0];
     34
     var orgId = firstArgument == null ? "" : firstArgument.getOrgId();
     35
     36
     37
     if (orgId == 1 || orgId == "1")
     { // 如果orgId == 1 ,只走最后一个节点,其余的走其他节点
         38
         var selectInvokers = new java.util.ArrayList(1);
         39 selectInvokers.add(availableInvokers.get(availableInvokers.size() - 1));
         40
         return selectInvokers;
         41
     }
     else
     {
         42
         var selectInvokers = new java.util.ArrayList(availableInvokers.size() - 1);
         43
         for (var i = 0; i < availableInvokers.size() - 1; i++)
         {
             44 selectInvokers.add(availableInvokers.get(i));
             45
         }
         46
         return selectInvokers;
         47
     }
     48
 }

向注册中心注册JS脚本路由规则

目前的dubbo-admin不支持在界面上注册路由规则,现给出基于JAVA代码来编写注册程序:

1 public static void main(String[] args) throws Exception
     {
         2 URL registryUrl = URL.valueOf("zookeeper://127.0.0.1:2181");
         3 ZookeeperRegistryFactory zookeeperRegistryFactory = new
         4 ZookeeperRegistryFactory();
         5 zookeeperRegistryFactory.setZookeeperTransporter(new 6 CuratorZookeeperTransporter());
         7 Registry zookeeperRegistry = (ZookeeperRegistry)
         8 zookeeperRegistryFactory.createRegistry(registryUrl);
         9 URL routerURL =
             10 URL.valueOf("script://0.0.0.0/com.alibaba.dubbo.demo.Demo
                 11 Service ? category = routers & dynamic = false & enabled = true & fo 12 rce = false & name = demoService_createUser_router & priority =
                 13 0 & runtime = true ");
                 14 routerURL = routerURL.addParameter("rule"
                     , 15 URL.encode(get_demoService_createUser_router())); 16 zookeeperRegistry.register(routerURL); // 注册
                 17 // zookeeperRegistry.unregister(routerURL); // 取消注册
                 18
             }

一旦运行上述代码,将会动态注册URL,服务提供者无需重启,下次服务调用后会自动生效(其背后原理是基于注册中心的动态发现)。

上述示例代码,我已经在本地环境,已能成功运行,并达到预期效果,公司项目需要根据自身的特点,特别服务方法的参数(例如合作伙伴ID的获取方式),以及路由需求来定制编写其路由脚本(js脚本)。

灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。当然我们在实现Dubbo灰度发布之前,一定要了解其原理,才能顺利进行开发!最后大家如果想要了解更多java架构师知识,敬请关注奇Q工具网。

推荐阅读:

java多线程面试题有哪些?java多线程面试题及答案

java地图定位如何实现?java怎么做定位打卡功能?

fastjson有哪些注解?fastjson注解妙用