美文网首页
Tars | 第3篇 Tars中期汇报测试文档(Java语言实现

Tars | 第3篇 Tars中期汇报测试文档(Java语言实现

作者: 多氯环己烷 | 来源:发表于2021-09-08 21:15 被阅读0次

    前言

    本篇为Tars项目上半程编程实践的测试结果,经过上半程的源码学习、编程探索,现已初步实现Subset流量路由的三个核心功能:按比例路由、按参数路由与无规则路由。下面将介绍任务需求、测试模拟方案以及具体的测试结果。


    1. 任务介绍

    下图为Subset流量管理任务需求 - 各语言SDK实现部分:

    各语言SDK实现

    本人的任务是:使用Java语言实现Subset路由规则,核心点在新增三种模式的路由规则:

    • 按比例路由;
    • 按参数路由,分为精确路由与正则路由;
    • 无规则路由;
    任务确认截图

    具体流程是

    • 获取路由规则参数;
    • 获取当前存活的服务节点;
    • 对节点进行Subset规则过滤【核心】;
    • 将过滤后的节点信息存入status传入下游;

    现在,在中期汇报前已完成初步编码,实现上述三种路由方式,下面将介绍笔者设计的测试方案,展示完成度

    2. 测试模拟方案

    测试采用Java SpringBoot的单元测试功能;

    测试思路是先模拟创建前置条件(添加路由规则与存活节点信息),接着调用filterEndpointsBySubset()方法进行测试,最后做些格式化处理。在这过程中输出过滤前后的节点信息。因此测试方案分为以下六步:

    1. 添加路由规则;
    2. 添加过滤前节点信息;
    3. 【输出】输出过滤前节点;
    4. 【核心】对存活节点按subset规则过滤;
    5. 对过滤后节点进行格式化处理;
    6. 【输出】输出过滤结果。

    2.0 *前置工作

    根据Java SpringBoot的单元测试规则,需要先构建一些测试用到的组件:

    //通信器配置项
    CommunicatorConfig communicatorConfig = new CommunicatorConfig();
    //查询助手
    QueryHelper queryHelper = new QueryHelper(new Communicator(communicatorConfig));
    //服务代理配置项
    ServantProxyConfig servantProxyConfig = new ServantProxyConfig("objectName");
    //节点列表
    List<EndpointF> endpointFList = new ArrayList<EndpointF>();
    //存活的节点
    Holder<List<EndpointF>> activeEp = new Holder<List<EndpointF>>(new ArrayList<EndpointF>());
    

    2.1 添加路由规则

    首先,根据任务需求文档说明书,可以知道新增路由规则的入参是类似下面JSON数据:

    [图片上传失败...(image-c234e4-1631106881409)]

    因此,笔者将上面信息存入servantProxyConfig服务代理配置项里,rule_data用一个map格式的数据来装配。下面代码用来模拟上游解析后的JSON数据,给通信器添加路由规则:

    //添加按比例路由规则
    servantProxyConfig.setRuleType("proportion");
    servantProxyConfig.setObjectName("objectName");
    Map<String,String> map = new HashMap<>();
    map.put("v1","20");
    map.put("v2","80");
    //map.put("v3",80);
    servantProxyConfig.setRuleData(map);
    

    2.2 添加存活节点

    在TarsJava里,节点保存在list集合里,直接add即可:

    //添加存活节点
    endpointFList.add(new EndpointF("host1",1,2,3,4,5,6,"setId1",7,8,9,10,"v1"));
    endpointFList.add(new EndpointF("host2",1,2,3,4,5,6,"setId2",7,8,9,10,"v1"));
    endpointFList.add(new EndpointF("host3",1,2,3,4,5,6,"setId3",7,8,9,10,"v2"));
    endpointFList.add(new EndpointF("host4",1,2,3,4,5,6,"setId4",7,8,9,10,"v2"));
    endpointFList.add(new EndpointF("host5",1,2,3,4,5,6,"setId5",7,8,9,10,"v2"));
    //endpointFList.add(new EndpointF("host5",1,2,3,4,5,6,"setId5",7,8,9,10,"v3"));
    
    activeEp.setValue(endpointFList);
    

    2.3 【输出】遍历输出当前存活节点

     //输出过滤前节点信息
            System.out.println("过滤前节点信息如下:");
            for( EndpointF endpoint : endpointFList){
                System.out.println(endpoint.toString());
            }
    

    2.4 【核心】对存活节点按subset规则过滤

    这是核心点,核心方法为filterEndpointsBySubset()按Subset规则过滤节点,这是笔者写的和测试的方法,它能够根据上述三种规则过滤节点:

    //对存活节点按subset规则过滤
    StringBuilder value = queryHelper.filterEndpointsBySubset(activeEp, servantProxyConfig);
    

    2.5 后续格式化处理

    这步将对过滤后的节点进行格式化处理:

    //后续格式化相关工作
    if (value.length() < 1) {
        System.out.println("value.length() < 1");
        return;
    }
    value.insert(0, Constants.TARS_AT);
    value.insert(0, servantProxyConfig.getSimpleObjectName());
    

    2.6 【输出】输出过滤结果

    这步输出过滤后的节点信息:

    //输出过滤结果
    System.out.println("过滤后节点信息如下:");
    System.out.println("result = " + value.toString());
    

    笔者的测试方案设计就这样分为六步,以下具体测试实例都是按照这六步进行。

    3. 按比例路由规则 - 单次测试

    具体测试方案为:节点有20%概率路由到Subset字段为v1的节点,有80概率路由到Subset字段为v2的节点【详情查看添加路由规则】。

    测试代码如下:

    /**
     * 按比例路由规则 - 单次测试
     */
    @Test
    public void testProportionOnce() {
    
        //添加按比例路由规则
        servantProxyConfig.setRuleType("proportion");
        servantProxyConfig.setObjectName("objectName");
        Map<String,String> map = new HashMap<>();
        map.put("v1","20");
        map.put("v2","80");
        servantProxyConfig.setRuleData(map);
    
        //添加存活节点
        endpointFList.add(new EndpointF("host1",1,2,3,4,5,6,"setId1",7,8,9,10,"v1"));
        endpointFList.add(new EndpointF("host2",1,2,3,4,5,6,"setId2",7,8,9,10,"v1"));
        endpointFList.add(new EndpointF("host3",1,2,3,4,5,6,"setId3",7,8,9,10,"v2"));
        endpointFList.add(new EndpointF("host4",1,2,3,4,5,6,"setId4",7,8,9,10,"v2"));
        endpointFList.add(new EndpointF("host5",1,2,3,4,5,6,"setId5",7,8,9,10,"v2"));
        
        activeEp.setValue(endpointFList);
    
        //输出过滤前节点信息
        System.out.println("过滤前节点信息如下:");
        for( EndpointF endpoint : endpointFList){
            System.out.println(endpoint.toString());
        }
    
        //对存活节点按subset规则过滤
        StringBuilder value = queryHelper.filterEndpointsBySubset(activeEp, servantProxyConfig);
    
        //后续格式化相关工作
        if (value.length() < 1) {
            System.out.println("value.length() < 1");
            return;
        }
        value.insert(0, Constants.TARS_AT);
        value.insert(0, servantProxyConfig.getSimpleObjectName());
    
        //输出过滤结果
        System.out.println("过滤后节点信息如下:");
        System.out.println("result = " + value.toString());
    }
    

    测试结果如下:

    按比例路由-单次测试
    结果分析:

    可以看出成功路由到v2节点,但还是无法体验到概率问题,于是有了下面按比例路由规则 - 多次测试

    4. 按比例路由规则 - 多次测试

    具体测试方案为:循环10000000次,统计路由结果,判断是否按比例路由。这里设置的比例是v1:v2:v3 = 20:80:20。

    测试代码如下:

    /**
     * 按比例路由规则 - 多次测试
     */
    @Test
    public void testProportionTimes() {
    
        //添加按比例路由规则
        servantProxyConfig.setRuleType("proportion");
        servantProxyConfig.setObjectName("objectName");
        Map<String,String> map = new HashMap<>();
        map.put("v1","20");
        map.put("v2","80");
        map.put("v3","20");
        servantProxyConfig.setRuleData(map);
    
        //添加存活节点
        endpointFList.add(new EndpointF("host1",1,2,3,4,5,6,"setId1",7,8,9,10,"v1"));
        endpointFList.add(new EndpointF("host2",1,2,3,4,5,6,"setId2",7,8,9,10,"v2"));
        endpointFList.add(new EndpointF("host3",1,2,3,4,5,6,"setId3",7,8,9,10,"v3"));
    
        activeEp.setValue(endpointFList);
    
        //循环times次
        int times = 10000000;
        int v1Times = 0;
        int v2Times = 0;
        int v3Times = 0;
        int errTimes = 0;
        for (int i = 0; i < times; i++) {
            //对存活节点按subset规则过滤
            StringBuilder value = queryHelper.filterEndpointsBySubset(activeEp, servantProxyConfig);
            //获取value的subset值
            String subset = null;
            if (value != null && value.length() > 3) {
                subset = value.substring(value.length() - 2);
                if("v1".equals(subset)){
                    v1Times++;
                } else if("v2".equals(subset)){
                    v2Times++;
                } else if("v3".equals(subset)){
                    v3Times++;
                }
            } else {
                errTimes++;
            }
    
        }
        //输出结果
        System.out.println("一共循环次数:" + times);
        System.out.println("路由到v1次数:" + v1Times);
        System.out.println("路由到v2次数:" + v2Times);
        System.out.println("路由到v3次数:" + v3Times);
        System.out.println("路由异常次数:" + errTimes);
    }
    

    测试结果如下:

    按比例路由 - 多次测试

    结果分析:

    可以看出结果比例接近v1:v2:v3 = 20:80:20,更改比例对应结果改变,按比例路由方法测试成功。

    5. 按参数路由规则测试

    具体测试方案为:设置染色的key为uid123,路由规则为精确(uid123) / 正则匹配(uid12*),路由规则跟染色key匹配,则路由到设置的v1;如果路由规则跟染色key不匹配,则无法路由,抛出错误信息。

    测试代码如下:

    /**
     * 按参数路由规则
     */
    @Test
    public void testParameterAccurate() {
    
        //添加按精确匹配路由规则
        servantProxyConfig.setRuleType("parameter");
        servantProxyConfig.setObjectName("objectName");
        Map<String,String> map = new HashMap<>();
    
        //精确匹配测试
        map.put("equal","uid123"); //精确匹配
        //map.put("equal","uid12");  //当染色key和请求的rule_type对不上时
    
        //正则匹配测试
        //map.put("match","uid12*");  //正则匹配
        //map.put("match","*d123");  //正则匹配
        //map.put("match","uid123");  //正则匹配
        //map.put("match","*id12*");  //正则匹配
    
        //map.put("match","*i12d*");
    
        map.put("route","v1");
        servantProxyConfig.setRuleData(map);
    
        //设置染色的key
        servantProxyConfig.setRouteKey("uid123");
    
        //添加存活节点
        endpointFList.add(new EndpointF("host1",1,2,3,4,5,6,"setId1",7,8,9,10,"v1"));
        endpointFList.add(new EndpointF("host2",1,2,3,4,5,6,"setId2",7,8,9,10,"v1"));
        endpointFList.add(new EndpointF("host3",1,2,3,4,5,6,"setId3",7,8,9,10,"v2"));
        endpointFList.add(new EndpointF("host4",1,2,3,4,5,6,"setId4",7,8,9,10,"v2"));
    
        activeEp.setValue(endpointFList);
    
        //输出过滤前节点信息
        System.out.println("过滤前节点信息如下:");
        for( EndpointF endpoint : endpointFList){
            System.out.println(endpoint.toString());
        }
        //对存活节点按subset规则过滤
        StringBuilder value = queryHelper.filterEndpointsBySubset(activeEp, servantProxyConfig);
        //后续格式化相关工作
        if (value.length() < 1) {
            System.out.println("找不到节点,value.length() < 1");
            return;
        }
        value.insert(0, Constants.TARS_AT);
        value.insert(0, servantProxyConfig.getSimpleObjectName());
    
        //输出过滤结果
        System.out.println("过滤后节点信息如下:");
        System.out.println("result = " + value.toString());
    
    }
    
    

    测试结果如下:

    按参数路由

    结果分析:

    经过测试,发现精确匹配路由成功;而正则匹配也能成功;当路由规则跟染色key不匹配时,则无法路由,输出结果如下图:

    找不到节点

    6. 按无路由规则测试

    具体测试方案为:无路由规则比较简单,直接传入{"default" , "v3" }路由规则即可,默认路由到v3;

    测试代码如下:

    /**
     * 按无路由规则
     */
    @Test
    public void testDefault() {
        //添加按比例路由规则
        servantProxyConfig.setRuleType("default");
        servantProxyConfig.setObjectName("objectName");
        Map<String,String> map = new HashMap<>();
        map.put("default","v3");
    
        servantProxyConfig.setRuleData(map);
    
        //添加存活节点
        endpointFList.add(new EndpointF("host1",1,2,3,4,5,6,"setId1",7,8,9,10,"v1"));
        endpointFList.add(new EndpointF("host2",1,2,3,4,5,6,"setId2",7,8,9,10,"v1"));
        endpointFList.add(new EndpointF("host3",1,2,3,4,5,6,"setId3",7,8,9,10,"v2"));
        endpointFList.add(new EndpointF("host4",1,2,3,4,5,6,"setId4",7,8,9,10,"v2"));
        endpointFList.add(new EndpointF("host5",1,2,3,4,5,6,"setId5",7,8,9,10,"v2"));
        endpointFList.add(new EndpointF("host5",1,2,3,4,5,6,"setId5",7,8,9,10,"v3"));
    
        activeEp.setValue(endpointFList);
    
        //输出过滤前节点信息
        System.out.println("过滤前节点信息如下:");
        for( EndpointF endpoint : endpointFList){
            System.out.println(endpoint.toString());
        }
    
        //对存活节点按subset规则过滤
        StringBuilder value = queryHelper.filterEndpointsBySubset(activeEp, servantProxyConfig);
    
        //后续格式化相关工作
        if (value.length() < 1) {
            System.out.println("value.length() < 1");
            return;
        }
        value.insert(0, Constants.TARS_AT);
        value.insert(0, servantProxyConfig.getSimpleObjectName());
    
        //输出过滤结果
        System.out.println("过滤后节点信息如下:");
        System.out.println("result = " + value.toString());
    }
    

    测试结果如下:

    按无路由规则

    结果分析:

    按照预设的默认规则能成功路由到v3。


    最后

    \color{blue}{\rm\small{新人制作,如有错误,欢迎指出,感激不尽!}}

    \color{blue}{\rm\small{欢迎关注我,并与我交流!}}

    \color{blue}{\rm\small{如需转载,请标注出处!}}

    相关文章

      网友评论

          本文标题:Tars | 第3篇 Tars中期汇报测试文档(Java语言实现

          本文链接:https://www.haomeiwen.com/subject/aekbwltx.html