前言
中期彙報會後,對Tars Subset功能更加熟悉,並根據TarsGo的實現方式,對Java JDK實現程式碼進行翻新改造。於是有了以下兩篇分析文章:
第5篇 基於TarsGo Subset路由規則的Java JDK實現方式(上篇)
https://www.cnblogs.com/dlhjw/p/15245113.html
第6篇 基於TarsGo Subset路由規則的Java JDK實現方式(下篇)
https://www.cnblogs.com/dlhjw/p/15245116.html
其中,《上篇》注重TarsGo分析,《下篇》注重TarsJava實現方式。不出意外的話,最終提交的考核成果就在下面的GitHub程式碼倉庫中(以下簡稱“最終程式碼”),後續可能會有些許地方需要更改:
TarsJava 實現Subset路由規則JDK GitHub開源地址
https://github.com/dlhjw/TarsJava/commit/cc2fe884ecbe8455a8e1f141e21341f4f3dd98a3
最終程式碼與中期程式碼在整體思想邏輯上都是一致的都是:先判斷Subset路由規則,再根據規則路由到定義的節點。不同點在於:中期在處理整個過程時,用一個方法filterEndpointsBySubset()
實現;而最終的實現方式則是以subsetEndpointFilter()
方法作為整個Subset流量路由的入口,通過subsetManager
管理器呼叫getSubset()
方法獲取到路由規則的String型別的subset
欄位,與節點自身的subset
欄位一一比較過濾節點;其中Subset路由規則的判斷封裝在getSubset()
方法裡;
總的來說就是最終程式碼是在處理subset規則邏輯中增加了很多細節,比如:通過新增的registry介面獲取subsetConf配置項;將獲取到是配置項存入快取中;以及將“判斷Subset路由規則”進行層層封裝,最終返回一個簡單的String型別的subset
欄位與節點自身的subset
欄位比較等;
因此,在測試方案上相比較中期有些許區別,但總體上的單元測試原則是不變的:
- 首先構建前置條件;
- 呼叫測試方法;
- 輸出測試結果;
其中的區別主要體現在前置條件的構建上,本篇將結合最終程式碼的實現邏輯,重點介紹其測試方案的設計;首先介紹測試方案的設計原則,接著針對五種情況(按比例單次、按比例多次、按引數精確、按引數正則路由與預設規則)做詳細介紹與展示測試結果。
最終程式碼的Subset執行流程分析請參考下面這篇文章:
第8篇 TarsJava Subset最終程式碼的執行流程與原理分析
https://blog.csdn.net/dlhjw1412/article/details/119932752
《測試方案設計》與《執行流程分析》兩篇文章相輔相成,相互觀閱能更快更好地理解整個Subset的業務流程與輸出示例;
1. SubsetConf配置項的結構
在中期,筆者使用一個map來模擬subset的流量規則;而在最終程式碼裡,是用多個物件來模擬Subset的配置,這些物件是理解整個Subset流量過濾規則的基礎的,因此很有必要在這裡做個介紹;
1.1 SubsetConf
public class SubsetConf {
private boolean enanle;
private String ruleType;
private RatioConfig ratioConf;
private KeyConfig keyConf;
private Instant lastUpdate;
……
}
可以看出SubsetConf配置項裡有以下屬性:
- enanle:表示是否開啟Subset流量管理功能;
- true:開啟;false:關閉;
- ruleType:表示流量管理的型別;
- 目前有
ratio
按比例和key
按引數兩種模式;
- 目前有
- RatioConfig:表示按比例路由配置項;
- 裡面定義了路由比例與路徑等資訊,詳情請參考《1.2 RatioConfig》
- KeyConfig:表示按引數路由配置項;
- 裡面定義了規則key與路由路徑等資訊,詳情請參考《1.3 KeyConfig》
- lastUpdate:表示該配置項上次更新時間,將在快取那裡起作用;
1.2 RatioConfig
public class RatioConfig {
private Map<String, Integer> rules;
……
}
RatioConfig裡只有一個map型別的rules
路由規則,其中key為一個String型別的subset欄位,用來跟節點的subset欄位匹配,value為路由權重,如:{ {"v1" , 20} , {"v2" , 60} , {"v3" , 20} }表示路由到subset欄位為v1的節點的概率為0.2;路由到subset欄位為v2的節點的概率為0.6;路由到subset欄位為v3的節點的概率為0.2;
1.3 KeyConfig
public class KeyConfig {
private String defaultRoute;
private List<KeyRoute> rules;
……
}
KeyConfig裡有兩個屬性,一個是defaultRoute
預設路由路徑;另一個是list型別的rules
,裡面是KeyRoute
,其定義了按引數匹配的型別、規則key與路徑,詳情請見《1.4 KeyRoute》
1.4 KeyRoute
public class KeyRoute {
private String action = null;
private String value = null;
private String route = null;
public static final String TARS_ROUTE_KEY = "TARS_ROUTE_KEY";
……
}
KeyRoute裡面有四個String型別的屬性,如下:
- action:用來定義引數匹配的型別;
- 目前可設定的型別有:equals精確匹配、match正則匹配、default預設匹配;
- value:這就是大名鼎鼎的規則key了。當action=equals時,還需滿足規則key與請求key匹配,才能進行精確匹配;當action=match時,還需滿足規則key與請求key正則匹配,才能進行正則匹配;action=default對規則key沒要求;
- route:用來規定路由路徑,其值為一個String型別的subset欄位,匹配到節點的subset欄位;
- TARS_ROUTE_KEY:一個常量欄位,為Tars請求體裡的status(map型別)的key;
1.5 SubsetConf的結構示意圖
上述提到的配置類聯絡結構圖如下:
2. 測試方案設計
這裡的測試主要指測試subsetEndpointFilter()根據subset過濾節點這一核心方法,在測試中構建前置條件最為複雜,因此將在2.1仔細介紹;
2.1 構建前置條件
從SubsetConf的結構圖可以看出,按比例與引數路由的一些前置條件不同,比如按引數路由需要一個list型別的KeyRoute,而按比例路由則是用一個map型別的資料結構實現類似KeyRoute的功能;
除此之外,KeyRoute裡的value為規則的key,其作用是與請求key做對比匹配,是引數匹配的必要不充分條件;這就要求構建前置條件時要考慮從Tars的請求體TarsServantRequest
中的status屬性(map型別)獲取到鍵TARS_ROUTE_KEY的值value,而Tars的請求體又要通過分散式上下文資訊DistributedContext
獲取;預設路由又不用考慮染色key……
因此,按比例與預設路由方式的前置條件包括:
- 一個Subset過濾器;
- 核心方法
subsetEndpointFilter
的傳入引數;- objectName:物件名;
- routeKey:上下文的染色key;
- activeEp:存活的節點列表及存活的節點;
- 一個SubsetManager管理器;
- RatioConfig比例路由規則;
- subsetConf配置項;
- 等;
可以通過以下程式碼實現、模擬:
//建立Subset過濾器
Subset subsetFilter = new Subset();
//模擬objectName
String objectName = "objectName";
//模擬routeKey
String routeKey = "routeKey";
//存活節點list列表
List<EndpointF> endpointFList = new ArrayList<EndpointF>();
Holder<List<EndpointF>> activeEp = new Holder<List<EndpointF>>(new ArrayList<EndpointF>());
//1. 給過濾器設定過濾規則
//1.1 建立SubsetManager管理器
SubsetManager subsetManager = new SubsetManager();
//1.1 設定比例路由規則
RatioConfig ratioConf = new RatioConfig();
Map<String , Integer> map = new HashMap<>();
map.put("v1",20);
map.put("v2",80);
//map.put("v3",20);
ratioConf.setRules(map);
//1.2 設定subsetConf,並加入快取
SubsetConf subsetConf = new SubsetConf();
subsetConf.setEnanle(true);
subsetConf.setRuleType("ratio");
subsetConf.setRatioConf(ratioConf);
subsetConf.setLastUpdate( Instant.now() );
Map<String, SubsetConf> cache = new HashMap<>();
cache.put(objectName,subsetConf);
subsetManager.setCache(cache);
//1.3 給過濾器設定過濾規則和管理者
subsetFilter.setSubsetConf(subsetConf);
subsetFilter.setSubsetManager(subsetManager);
//2. 模擬存活節點
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);
而按引數匹配路由方式的前置條件包括:
- 一個Subset過濾器;
- 核心方法
subsetEndpointFilter
的傳入引數;- objectName:物件名;
- routeKey:上下文的染色key;
- activeEp:存活的節點列表及存活的節點;
- 一個SubsetManager管理器;
- KeyConfig引數路由規則;
- KeyRoute引數路由屬性;
- subsetConf配置項;
- Tars的請求體TarsServantRequest;
- 一個Session域,用來構建Tars請求體
- 分散式上下文資訊DistributedContext;
- 等;
可以通過以下程式碼實現、模擬:
//建立Subset過濾器
Subset subsetFilter = new Subset();
//模擬objectName
String objectName = "objectName";
//模擬routeKey
String routeKey = "routeKey";
//存活節點list列表
List<EndpointF> endpointFList = new ArrayList<EndpointF>();
Holder<List<EndpointF>> activeEp = new Holder<List<EndpointF>>(new ArrayList<EndpointF>());
//定義一個Session域,用來構建Tars請求體
Session session;
//1. 給過濾器設定過濾規則
//1.1 建立SubsetManager管理器
SubsetManager subsetManager = new SubsetManager();
//1.1 設定引數路由規則,這裡的KeyRoute的value為 “規則的染色key”
KeyConfig keyConf = new KeyConfig();
List<KeyRoute> krs = new LinkedList<>();
krs.add(new KeyRoute("match","routeKey","v1"));
keyConf.setRules(krs);
//1.2 設定subsetConf,並加入快取
SubsetConf subsetConf = new SubsetConf();
subsetConf.setEnanle(true);
subsetConf.setRuleType("key");
subsetConf.setKeyConf(keyConf);
subsetConf.setLastUpdate( Instant.now() );
Map<String, SubsetConf> cache = new HashMap<>();
cache.put(objectName,subsetConf);
subsetManager.setCache(cache);
//1.3 給過濾器設定過濾規則和管理者
subsetFilter.setSubsetConf(subsetConf);
subsetFilter.setSubsetManager(subsetManager);
//1.4 模擬Tars “請求的染色key” TARS_ROUTE_KEY,但請求染色key和規則染色key匹配時,才能精確路由
//1.4.1 建立Tars的請求體TarsServantRequest
TarsServantRequest request = new TarsServantRequest( session );
//1.4.2 往請求體的status新增{TARS_ROUTE_KEY, "routeKey"}鍵值對
Map<String, String> status = new HashMap<>();
status.put("TARS_ROUTE_KEY", "routeKey");
request.setStatus(status);
//1.4.3 構建分散式上下文資訊,將請求放入分散式上下文資訊中,因為getSubset()的邏輯是從分散式上下文資訊中取
DistributedContext distributedContext = new DistributedContextImpl();
distributedContext.put(DyeingSwitch.REQ,request);
//2. 模擬存活節點
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.2 呼叫測試方法
呼叫測試方法比較簡單,用如下語句實現即可:
//4. 對存活節點按subset規則過濾
Holder<List<EndpointF>> filterActiveEp = subsetFilter.subsetEndpointFilter(objectName, routeKey, activeEp);
2.3 輸出測試結果
輸出測試結果也比較簡單,在過濾前後都遍歷一些節點列表,判斷其是否起到過濾功能即可,可以用如下程式碼實現:
//3. 輸出過濾前資訊
System.out.println("過濾前節點資訊如下:");
for( EndpointF endpoint : endpointFList){
System.out.println(endpoint.toString());
}
//5. 輸出過濾結果
System.out.println("過濾後節點資訊如下:");
for( EndpointF endpoint : filterActiveEp.getValue() ){
System.out.println(endpoint.toString());
}
如此,一個大概的測試方案就成型了,下面將介紹各路由方式的測試程式碼與測試結果;
3. 按比例路由規則 - 單次測試
測試程式碼如下:
/**
* 按比例路由規則 - 單次測試
* 沒有測試registry獲取subsetConf功能
*/
@Test
public void testRatioOnce() {
//1. 給過濾器設定過濾規則
//1.1 建立SubsetManager管理器
SubsetManager subsetManager = new SubsetManager();
//1.1 設定比例路由規則
RatioConfig ratioConf = new RatioConfig();
Map<String , Integer> map = new HashMap<>();
map.put("v1",20);
map.put("v2",80);
//map.put("v3",20);
ratioConf.setRules(map);
//1.2 設定subsetConf,並加入快取
SubsetConf subsetConf = new SubsetConf();
subsetConf.setEnanle(true);
subsetConf.setRuleType("ratio");
subsetConf.setRatioConf(ratioConf);
subsetConf.setLastUpdate( Instant.now() );
Map<String, SubsetConf> cache = new HashMap<>();
cache.put(objectName,subsetConf);
subsetManager.setCache(cache);
//1.3 給過濾器設定過濾規則和管理者
subsetFilter.setSubsetConf(subsetConf);
subsetFilter.setSubsetManager(subsetManager);
//2. 模擬存活節點
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);
//3. 輸出過濾前資訊
System.out.println("過濾前節點資訊如下:");
for( EndpointF endpoint : endpointFList){
System.out.println(endpoint.toString());
}
//4. 對存活節點按subset規則過濾
Holder<List<EndpointF>> filterActiveEp = subsetFilter.subsetEndpointFilter(objectName, routeKey, activeEp);
//5. 輸出過濾結果
System.out.println("過濾後節點資訊如下:");
for( EndpointF endpoint : filterActiveEp.getValue() ){
System.out.println(endpoint.toString());
}
}
測試結果如下:
在上述情況下,如果我們將所有v2節點刪除,即模擬經過按比例權重查詢後匹配到節點subset欄位為v2集合,但原來存活節點裡卻沒有subset欄位為v2的節點這種情況,將會輸出一句錯誤資訊,如下:
4. 按比例路由規則 - 多次測試
測試程式碼如下:
/**
* 按比例路由規則 - 多次測試
* 沒有測試registry獲取subsetConf功能
*/
@Test
public void testRatioTimes() {
//1. 給過濾器設定過濾規則
//1.1 建立SubsetManager管理器
SubsetManager subsetManager = new SubsetManager();
//1.1 設定比例路由規則
RatioConfig ratioConf = new RatioConfig();
Map<String , Integer> map = new HashMap<>();
map.put("v1",20);
map.put("v2",80);
map.put("v3",20);
ratioConf.setRules(map);
//1.2 設定subsetConf,並加入快取
SubsetConf subsetConf = new SubsetConf();
subsetConf.setEnanle(true);
subsetConf.setRuleType("ratio");
subsetConf.setRatioConf(ratioConf);
subsetConf.setLastUpdate( Instant.now() );
Map<String, SubsetConf> cache = new HashMap<>();
cache.put(objectName,subsetConf);
subsetManager.setCache(cache);
//1.3 給過濾器設定過濾規則和管理者
subsetFilter.setSubsetConf(subsetConf);
subsetFilter.setSubsetManager(subsetManager);
//2. 模擬存活節點
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);
//3. 迴圈times次
int times = 1000000;
int v1Times = 0;
int v2Times = 0;
int v3Times = 0;
int errTimes = 0;
for (int i = 0; i < times; i++) {
//對存活節點按subset規則過濾
Holder<List<EndpointF>> filterActiveEp = subsetFilter.subsetEndpointFilter(objectName, routeKey, activeEp);
String subsetValue = filterActiveEp.getValue().get(0).getSubset();
if("v1".equals(subsetValue)){
v1Times++;
} else if("v2".equals(subsetValue)){
v2Times++;
} else if("v3".equals(subsetValue)){
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);
}
測試結果如下:
這裡如果我們將語句subsetConf.setEnanle(true);
中的true置為false,可以發現沒有起到路由功能,所有結點路由到v1那邊,如下圖所示:
如果我們給方法subsetEndpointFilter(objectName, routeKey, activeEp)
中的routeKey傳入引數為空字串""
,則會等比例隨機路由,測試結果如下:
5. 按引數路由規則 - 精確匹配測試
測試程式碼如下:
/**
* 測試引數匹配 - 精確匹配
* 沒有測試registry獲取subsetConf功能
* 注意要成功必須routeKey和match匹配上
*/
@Test
public void testMatch() {
//1. 給過濾器設定過濾規則
//1.1 建立SubsetManager管理器
SubsetManager subsetManager = new SubsetManager();
//1.1 設定引數路由規則,這裡的KeyRoute的value為 “規則的染色key”
KeyConfig keyConf = new KeyConfig();
List<KeyRoute> krs = new LinkedList<>();
krs.add(new KeyRoute("match","routeKey","v1"));
keyConf.setRules(krs);
//1.2 設定subsetConf,並加入快取
SubsetConf subsetConf = new SubsetConf();
subsetConf.setEnanle(true);
subsetConf.setRuleType("key");
subsetConf.setKeyConf(keyConf);
subsetConf.setLastUpdate( Instant.now() );
Map<String, SubsetConf> cache = new HashMap<>();
cache.put(objectName,subsetConf);
subsetManager.setCache(cache);
//1.3 給過濾器設定過濾規則和管理者
subsetFilter.setSubsetConf(subsetConf);
subsetFilter.setSubsetManager(subsetManager);
//1.4 模擬Tars “請求的染色key” TARS_ROUTE_KEY,但請求染色key和規則染色key匹配時,才能精確路由
//1.4.1 建立Tars的請求體TarsServantRequest
TarsServantRequest request = new TarsServantRequest( session );
//1.4.2 往請求體的status新增{TARS_ROUTE_KEY, "routeKey"}鍵值對
Map<String, String> status = new HashMap<>();
status.put("TARS_ROUTE_KEY", "routeKey");
request.setStatus(status);
//1.4.3 構建分散式上下文資訊,將請求放入分散式上下文資訊中,因為getSubset()的邏輯是從分散式上下文資訊中取
DistributedContext distributedContext = new DistributedContextImpl();
distributedContext.put(DyeingSwitch.REQ,request);
//2. 模擬存活節點
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);
//3. 輸出過濾前資訊
System.out.println("過濾前節點資訊如下:");
for( EndpointF endpoint : endpointFList){
System.out.println(endpoint.toString());
}
//4. 對存活節點按subset規則過濾
Holder<List<EndpointF>> filterActiveEp = subsetFilter.subsetEndpointFilter(objectName, routeKey, activeEp);
//5. 輸出過濾結果
System.out.println("過濾後節點資訊如下:");
for( EndpointF endpoint : filterActiveEp.getValue() ){
System.out.println(endpoint.toString());
}
}
測試結果如下:
這裡如果我們使規則key與請求key不匹配,將起不到過濾功能,並輸出一句錯誤日誌,如下圖所示:
6. 按引數路由規則 - 正則匹配測試
測試程式碼如下:
/**
* 測試引數匹配 - 正則匹配
* 沒有測試registry獲取subsetConf功能
* 注意要成功必須routeKey和match匹配上
*/
@Test
public void testEqual() {
//1. 給過濾器設定過濾規則
//1.1 建立SubsetManager管理器
SubsetManager subsetManager = new SubsetManager();
//1.1 設定引數路由規則,這裡的KeyRoute的value為 “規則的染色key”
KeyConfig keyConf = new KeyConfig();
List<KeyRoute> krs = new LinkedList<>();
krs.add(new KeyRoute("equal","routeKey","v1"));
keyConf.setRules(krs);
//1.2 設定subsetConf,並加入快取
SubsetConf subsetConf = new SubsetConf();
subsetConf.setEnanle(true);
subsetConf.setRuleType("key");
subsetConf.setKeyConf(keyConf);
subsetConf.setLastUpdate( Instant.now() );
Map<String, SubsetConf> cache = new HashMap<>();
cache.put(objectName,subsetConf);
subsetManager.setCache(cache);
//1.3 給過濾器設定過濾規則和管理者
subsetFilter.setSubsetConf(subsetConf);
subsetFilter.setSubsetManager(subsetManager);
//1.4 模擬Tars “請求的染色key” TARS_ROUTE_KEY,但請求染色key和規則染色key匹配時,才能精確路由
//1.4.1 建立Tars的請求體TarsServantRequest
TarsServantRequest request = new TarsServantRequest( session );
//1.4.2 往請求體的status新增{TARS_ROUTE_KEY, "routeKey"}鍵值對
Map<String, String> status = new HashMap<>();
status.put("TARS_ROUTE_KEY", "route*");
request.setStatus(status);
//1.4.3 構建分散式上下文資訊,將請求放入分散式上下文資訊中,因為getSubset()的邏輯是從分散式上下文資訊中取
DistributedContext distributedContext = new DistributedContextImpl();
distributedContext.put(DyeingSwitch.REQ,request);
//2. 模擬存活節點
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);
//3. 輸出過濾前資訊
System.out.println("過濾前節點資訊如下:");
for( EndpointF endpoint : endpointFList){
System.out.println(endpoint.toString());
}
//4. 對存活節點按subset規則過濾
Holder<List<EndpointF>> filterActiveEp = subsetFilter.subsetEndpointFilter(objectName, routeKey, activeEp);
//5. 輸出過濾結果
System.out.println("過濾後節點資訊如下:");
for( EndpointF endpoint : filterActiveEp.getValue() ){
System.out.println(endpoint.toString());
}
}
測試結果如下:
這裡如果我們使規則key與請求key正則匹配不上,跟精確匹配一樣將起不到過濾功能,並輸出一句錯誤日誌,如下圖所示:
7. 無路由規則測試
測試程式碼如下:
/**
* 測試預設路由
* 沒有測試registry獲取subsetConf功能
*/
@Test
public void testDefault() {
//1. 給過濾器設定過濾規則
//1.1 建立SubsetManager管理器
SubsetManager subsetManager = new SubsetManager();
//1.1 設定引數路由規則,這裡的KeyRoute的value為 “規則的染色key”
KeyConfig keyConf = new KeyConfig();
List<KeyRoute> krs = new LinkedList<>();
krs.add(new KeyRoute("default","","v1"));
keyConf.setRules(krs);
//1.2 設定subsetConf,並加入快取
SubsetConf subsetConf = new SubsetConf();
subsetConf.setEnanle(true);
subsetConf.setRuleType("key");
subsetConf.setKeyConf(keyConf);
subsetConf.setLastUpdate( Instant.now() );
Map<String, SubsetConf> cache = new HashMap<>();
cache.put(objectName,subsetConf);
subsetManager.setCache(cache);
//1.3 給過濾器設定過濾規則和管理者
subsetFilter.setSubsetConf(subsetConf);
subsetFilter.setSubsetManager(subsetManager);
//2. 模擬存活節點
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);
//3. 輸出過濾前資訊
System.out.println("過濾前節點資訊如下:");
for( EndpointF endpoint : endpointFList){
System.out.println(endpoint.toString());
}
//4. 對存活節點按subset規則過濾
Holder<List<EndpointF>> filterActiveEp = subsetFilter.subsetEndpointFilter(objectName, routeKey, activeEp);
//5. 輸出過濾結果
System.out.println("過濾後節點資訊如下:");
for( EndpointF endpoint : filterActiveEp.getValue() ){
System.out.println(endpoint.toString());
}
}
測試結果如下: