spring cloud gateway 二次開發之 動態路由注意事項


https://www.codenong.com/jsf04a503f0d32/

 

 

spring cloud gateway 二次開發之 動態路由注意事項

 

網關開發的過程中,因為有對某些服務進行動態的上下線的需求,所以進行了動態路由的開發,網上也有例子,實現方式就不贅述了,但這里有2個注意事項。

 

一 路由信息里的斷言器信息不能為空

如果沒有傳斷言器信息,比如這樣

 

1
2
3
4
5
6
7
{
    "id":"test",
    "predicates":[],
    "filters":[],
    "uri":"lb://test",
    "order":0
}

會拋出異常

 

1
2
3
4
5
6
reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
    at java.util.ArrayList.rangeCheck(ArrayList.java:653)
    at java.util.ArrayList.get(ArrayList.java:429)
    at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.combinePredicates(RouteDefinitionRouteLocator.java:221)
    at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.convertToRoute(RouteDefinitionRouteLocator.java:143)

我們看路由信息類的時候,可以發現斷言器是一個List,RouteDefinitionRouteLocator下邊有這個方法,會先取List中第一個斷言器,然后與之后的斷言器做組合,

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private AsyncPredicate<ServerWebExchange> combinePredicates(
            RouteDefinition routeDefinition) {
        List<PredicateDefinition> predicates = routeDefinition.getPredicates();
        //取出第一個斷言器
        AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition,
                predicates.get(0));

       //取出后續斷言器
        for (PredicateDefinition andPredicate : predicates.subList(1,
                predicates.size())) {
            AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition,
                    andPredicate);
       //第一個斷言器和后續斷言器做 and 操作
            predicate = predicate.and(found);
        }

        return predicate;
    }

 

 

如果沒有填斷言器信息,就會報數組越界異常

 

二 斷言器的名字不能隨便取

比如這里我取了一個 zuibuxing 的斷言器名字

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
    "id":"test",
    "predicates":[
        {
            "name":"zuibuxing",
            "args":{
                "_genkey_0":"/test/**"
            }
        }
    ],
    "filters":[

    ],
    "uri":"lb://test",
    "order":0
}

會報這個錯誤

 

1
2
3
4
5
reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IllegalArgumentException: Unable to find RoutePredicateFactory with name zuibuxing
Caused by: java.lang.IllegalArgumentException: Unable to find RoutePredicateFactory with name zuibuxing
    at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.lookup(RouteDefinitionRouteLocator.java:240)
    at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.combinePredicates(RouteDefinitionRouteLocator.java:220)
    at org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator.convertToRoute(RouteDefinitionRouteLocator.java:143)

說找不到名字為 zuibuxing 的斷言器,這是因為保存自定義路由的時候,RouteDefinitionRouteLocato 會按照 name 去斷言器Map 里去尋找,

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private final Map<String, RoutePredicateFactory> predicates = new LinkedHashMap<>();

... 中間代碼省略 ....

//按照名字尋找斷言器
private AsyncPredicate<ServerWebExchange> lookup(RouteDefinition route,
            PredicateDefinition predicate) {
        RoutePredicateFactory<Object> factory = this.predicates.get(predicate.getName());
        if (factory == null) {
            throw new IllegalArgumentException(
                    "Unable to find RoutePredicateFactory with name "
                            + predicate.getName());
        }

        ...以下代碼省略
    }
1
 

 

 

RouteDefinitionRouteLocator 在這個Map中保存所有實現了 RoutePredicateFactory 的類,name是類名去掉RoutePredicateFactory,比如 AfterRoutePredicateFactory 斷言器的名字是 After,這里有兩個特殊的斷言器 CloudFoundryRouteService,ReadBodyPredicateFactory,因為它們的類名沒有以 RoutePredicateFactory 結尾,所以就用本身類名作為 斷言器name
如果是隨便寫的,會導致找不到斷言器報錯,所以我們只能填gateway自己的斷言器,或者自己實現了 RoutePredicateFactory 的斷言器


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM