Spring Cloud Gateway——實現路由動態修改

動態路由修改

當我們看了Spring Cloud Gateway的示例代碼,和一些網上的入門教程之後,會發現大多是Spring Cloud Gateway — 網關基本功能API暴露說道的三種方法:1.本地配置文件;2.java代碼builder.routes().route().build(); 3.服務自動發現。

服務自動發現方法能夠做到後端服務ip變化時自動更新,能夠做到上游服務的動態。另外兩種方式都是純靜態,需要重新啓動網關服務修改才能生效。

上述方式都不能完全滿足生產需要,一般來說作爲生產上的通用網關要求有路由動態修改能力,不重啓網關服務即可即使生效。無論是新增路由、或者是修改路由的過濾規則,添加過濾器都可以不重啓網關生效。

內置的動態路由

Spring Cloud Gateway內置了一個動態路由類InMemoryRouteDefinitionRepository。這是一個使用內存存儲路由的類,支持acurator接口對路由進行增刪改查,但是當網關重啓之後所有的內存路由都會消失,也就是說它沒有持久化能力。

雖然InMemoryRouteDefinitionRepository沒有達到生產級動態路由修改的需求,但是它提供了一種思路,起到了示例作用。如果需要實現自己的可持久化動態路由,可以仿照InMemoryRouteDefinitionRepository的路由解析加載能力,以及更新方式實現在即的動態路由。

基於分佈式配置的動態路由

基於分佈式配置可能是一種最簡單便捷的路由動態修改能力了,這裏展示基於spring cloud config實現Spring Cloud Gateway動態路由修改。

/**
 * a route definition locator, that locate route definition from remote config server or local properties file.
 * route definition is json value, not yaml value, e.g.
 * "route-definitions=[{\"id\": \"websocket_test\",\"uri\": \"ws://localhost:9000\",\"order\": 9000,\"predicates\":[\"Path=/echo\"],\"filters\":[\"AddRequestHeader=x-tt-token, 123456\"]}]"
 * or
 * "route-definitions=[{\"id\": \"websocket_test\",\"uri\": \"ws://localhost:9000\",\"order\": 9000,\"predicates\":[{\"name\":\"Path\", \"args\":{\"_genkey_0\":\"/echo\"}}],\"filters\":[{\"name\":\"AddRequestHeader\", \"args\":{\"_genkey_0\":\"x-tt-token\",\"_genkey_1\":\"123456\"}}]}]"
 *
 * compare to spring cloud gateway's default InMemoryRouteDefinitionRepository, route definitions could be loaded when program's startup.
 *
 * to do this, there is another way. define a bean and load remote route definitions to InMemoryRouteDefinitionRepository when program's startup.
 * otherwise, you should implement ApplicationListener<ApplicationEvent>. when refresh event emited, remote route definitions should be reloaded
 * into InMemoryRouteDefinitionRepository.
 */
public class ConfigServerRouteDefinitionLocator implements RouteDefinitionLocator {
    @Value("${route-definitions}")
    private String routeDefinitions;//a json string, contains route definition lists

    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        ObjectMapper mapper = new ObjectMapper();
        List<RouteDefinition> rdList = null;
        try {
            System.out.println(routeDefinitions);
            rdList = mapper.readValue(routeDefinitions, new TypeReference<List<RouteDefinition>>() { });
            return Flux.fromArray(rdList.toArray(new RouteDefinition[]{}));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return Flux.empty();
    }
}

方法很簡單,只需要在config server裏增加一個路由的配置項即可。config server可以調用Spring Cloud Gateway的路由更新接口/refresh,路由配置就會自動更新。

如果要實現更復雜的控制邏輯,比如路由配置的路由校驗、版本控制、灰度發佈等其他功能,可以在定義自己的refresh接口和管理後臺進行控制。

其他方式

如果時間允許,可以使用其他存儲方式實現路由動態修改能力。可以參考以下文章:

基於Redis實現動態路由修改
基於Redis實現動態路由修改-其中的金絲雀是對上游的金絲雀發佈,不是對網關自身的金絲雀控制,這種用法一般不太常見

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章