Tars | 第3篇 Tars中期彙報測試文件(Java語言實現Subset路由規則)

多氯環己烷發表於2021-09-08


前言

本篇為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資料:

JSON資料

因此,筆者將上面資訊存入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。


最後

新人制作,如有錯誤,歡迎指出,感激不盡!
歡迎關注公眾號,會分享一些更日常的東西!
如需轉載,請標註出處!
Tars | 第3篇 Tars中期彙報測試文件(Java語言實現Subset路由規則)

相關文章