客製 Spring Cloud Gateway 路由表 並儲存至 Redis

栏目: Java · 发布时间: 6年前

内容简介:功能:希望外部訪問並且將路由資訊儲存至 Redis 下次重啟 or 增加新的 gateway 不用重新配置路由資訊.

功能:

希望外部訪問 http://domain/acc/v1/endpoint 時, 可以轉發到 springcloud 中 ACC-V1 的實例,

並且將路由資訊儲存至 Redis 下次重啟 or 增加新的 gateway 不用重新配置路由資訊.

配置部分

application.yml

spring:
  application:
    name: gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: false
  redis:
    host: 127.0.0.1
    port: 6379
    password:
server:
  port: ${port:9000}
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    prefer-ip-address: true
management:
  endpoints:
    web:
      exposure:
        include: '*'

關閉由服務發現來建立路由

spring.cloud.gateway.discovery.locator.enabled = false

開放 gateway 的 endpoint

management.endpoints.web.exposure.include = "*"

程式部分

準備兩支

Redis 配置

RedisConfig.java

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

需要配置使用 Json 儲存到 Redis, 因為 org.springframework.cloud.gateway.route.RouteDefinition 並沒有 implements Serializable,

所以不轉成 Json 會出錯.

實作 RouteDefinitionRepository

RedisRouteDefinitionRepository.java

@Slf4j
@Component
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
    public static final String GATEWAY_ROUTES = "geteway_routes";

    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        List<RouteDefinition> routeDefinitions = new ArrayList<>();
        redisTemplate.opsForHash().values(GATEWAY_ROUTES).stream().forEach(routeDefinition -> {
            try {
                routeDefinitions.add((RouteDefinition) routeDefinition);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return Flux.fromIterable(routeDefinitions);
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return route
                .flatMap(routeDefinition -> {
                    redisTemplate.opsForHash().put(GATEWAY_ROUTES, routeDefinition.getId(),
                            routeDefinition);
                    return Mono.empty();
                });
    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return routeId.flatMap(id -> {
            if (redisTemplate.opsForHash().hasKey(GATEWAY_ROUTES, id)) {
                redisTemplate.opsForHash().delete(GATEWAY_ROUTES, id);
                return Mono.empty();
            }
            return Mono.defer(() -> Mono.error(new NotFoundException("RouteDefinition not found: " + routeId)));
        });
    }
}

gateway 預設是將路由放在記憶體中管理, 但當發現有額外提供 RouteDefinitionRepository 時則會採用你提供的,

這邊實作則是將路由寫到 Redis 做存放.

看一下 Eureka 上有哪些服務

客製 Spring Cloud Gateway 路由表 並儲存至 Redis

跟 gateway 要路由表資訊看看

curl -X GET http://localhost:9000/actuator/gateway/routes

ResponseBody

[]

可以看到路由表是空的

新增路由

curl -X POST \
  http://localhost:9000/actuator/gateway/routes/acc_v1 \
  -H 'Content-Type: application/json' \
  -d '{
  "predicates": [
    {
      "name": "Path",
      "args": {
        "pattern": "/ACC/V1/**"
      }
    }
  ],
  "filters": [
    {
      "name": "RewritePath",
      "args": {
        "regexp": "/ACC/V1/(?<remaining>.*)",
        "replacement": "/${remaining}"
      }
    }
  ],
  "uri": "lb://ACC-V1",
  "order": 0
}'

再次做查詢

curl -X GET http://localhost:9000/actuator/gateway/routes

ResponseBody

[
    {
        "route_id": "acc_v1",
        "route_definition": {
            "id": "acc_v1",
            "predicates": [
                {
                    "name": "Path",
                    "args": {
                        "pattern": "/ACC/V1/**"
                    }
                }
            ],
            "filters": [
                {
                    "name": "RewritePath",
                    "args": {
                        "regexp": "/ACC/V1/(?<remaining>.*)",
                        "replacement": "/${remaining}"
                    }
                }
            ],
            "uri": "lb://ACC-V1",
            "order": 0
        },
        "order": 0
    }
]

此時可以發現已經有路由表了, 也去 Redis 查一下

客製 Spring Cloud Gateway 路由表 並儲存至 Redis

接下來去請求 ACC-V1 的資料

curl -X GET http://localhost:9000/ACC/V1/version

ResponseBody

{
    "appName": "acc-v1"
}

可以正確拿到v1的資料

此時啟動新的服務版本是 v2

客製 Spring Cloud Gateway 路由表 並儲存至 Redis

這時候去拿 v2 資料是拿不到

curl -X GET http://localhost:9000/ACC/V2/version

ResponseBody

{
    "timestamp": "2018-11-07T09:11:10.323+0000",
    "path": "/ACC/V2/version",
    "status": 404,
    "error": "Not Found",
    "message": null
}

增加新服務路由 v2

curl -X POST \
  http://localhost:9000/actuator/gateway/routes/acc_v2 \
  -H 'Content-Type: application/json' 
  -d '{
  "predicates": [
    {
      "name": "Path",
      "args": {
        "pattern": "/ACC/V2/**"
      }
    }
  ],
  "filters": [
    {
      "name": "RewritePath",
      "args": {
        "regexp": "/ACC/V2/(?<remaining>.*)",
        "replacement": "/${remaining}"
      }
    }
  ],
  "uri": "lb://ACC-V2",
    "order": 0
}'

這時候去拿 v2 的資料就可以正確取得

curl -X GET http://localhost:9000/ACC/V2/version

ResponseBody

{
    "appName": "acc-v2"
}

但服務 acc-v1 還是可以訪問到, v1 v2 服務同時提供服務, 並且透過 url 來指定就完成了

curl -X GET http://localhost:9000/ACC/V1/version

ResponseBody

{
    "appName": "acc-v1"
}

當 v1 要廢棄的時候, 可以先透過 management.endpoints 來刪除

curl -X DELETE \
  http://localhost:9000/actuator/gateway/routes/acc_v1

刪除之後確定沒問題就可以真正的把服務關掉囉

curl -X GET \
  http://localhost:9000/actuator/gateway/routes

ResponseBody

[
    {
        "route_id": "acc_v2",
        "route_definition": {
            "id": "acc_v2",
            "predicates": [
                {
                    "name": "Path",
                    "args": {
                        "pattern": "/ACC/V2/**"
                    }
                }
            ],
            "filters": [
                {
                    "name": "RewritePath",
                    "args": {
                        "regexp": "/ACC/V2/(?<remaining>.*)",
                        "replacement": "/${remaining}"
                    }
                }
            ],
            "uri": "lb://ACC-V2",
            "order": 0
        },
        "order": 0
    }
]

當 gateway 重啟或是增加新的時候, 都會去 Redis 取得路由資訊, 這樣就不用一個一個去配置啦

如果手動增加或刪除 Redis 內的路由資訊, 其實也是可以同步到所有 Gateway 上, 這樣也不一定需要開 management.endpoints gateway.


以上所述就是小编给大家介绍的《客製 Spring Cloud Gateway 路由表 並儲存至 Redis》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

生物信息学算法导论

生物信息学算法导论

N.C.琼斯 / 第1版 (2007年7月1日) / 2007-7 / 45.0

这是一本关于生物信息学算法和计算思想的导论性教科书,原著由国际上的权威学者撰写,经国内知名专家精心翻译为中文,系统介绍推动生物信息学不断进步的算法原理。全书强调的是算法中思想的运用,而不是对表面上并不相关的各类问题进行简单的堆砌。 体现了以下特色: 阐述生物学中的相关问题,涉及对问题的模型化处理并提供一种或多种解决方案: 简要介绍生物信息学领域领军人物; 饶有趣味的小插图使得概念更加具体和形象,方......一起来看看 《生物信息学算法导论》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具