Spring Cloud GateWay中通过数据库来存储路由配置规则?

发布时间:2024-09-16

Image

Spring Cloud Gateway是Spring Cloud生态系统中的一个重要组件,它作为微服务架构中的API网关,负责将外部请求路由到相应的微服务实例。默认情况下,Gateway的路由配置规则是通过application.yml配置文件或Nacos、Apollo等配置中心来存储的。然而,在某些场景下,我们可能需要将这些路由配置规则存储在数据库中,以便实现更灵活的动态管理和权限控制。

要实现这一点,最简单的方法是让Gateway服务实现ApplicationEventPublisherAware接口,并扩展其数据存取方案。具体来说,我们需要在Gateway服务中新增entity、mapper、service和controller等模块,用于对数据库中的路由配置信息进行增删改查操作。例如,我们可以设计一个简单的MySQL数据库表routes_config,包含id、uri、predicates、filters和remarks等字段,用于存储路由配置信息。

在Gateway的配置文件中,我们需要注释掉原有的静态路由配置,并引入数据库连接配置。例如:

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.139.128:3306/gatewayDb?characterEncoding=utf8&allowMultiQueries=true&useSSL=false
    username: root
    password: root

接下来,我们需要在RouteService类中实现ApplicationEventPublisherAware接口,并通过CommandLineRunner接口让服务启动时自动从数据库加载路由配置信息。具体实现可以参考以下代码片段:

@Component
@Slf4j
public class RouteService implements ApplicationEventPublisherAware, CommandLineRunner {

    private ApplicationEventPublisher publisher;
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    @Autowired
    private RouteMapper routeMapper;

    @Override
    public void run(String... args) throws Exception {
        List<RouteEntity> routeEntities = routeMapper.selectList(null);
        if (CollectionUtils.isNotEmpty(routeEntities)) {
            for (RouteEntity routeEntity : routeEntities) {
                RouteDefinition routeDefinition = new RouteDefinition();
                routeDefinition.setId(routeEntity.getId());
                routeDefinition.setUri(URI.create(routeEntity.getUri()));
                List<PredicateDefinition> predicateDefinitions = new ArrayList<>();
                predicateDefinitions.add(new PredicateDefinition("Path", routeEntity.getPredicates()));
                routeDefinition.setPredicates(predicateDefinitions);
                Map<String, FilterDefinition> filterDefinitions = new HashMap<>();
                filterDefinitions.put("StripPrefix", new FilterDefinition("StripPrefix", Arrays.asList(routeEntity.getFilters())));
                routeDefinition.setFilters(filterDefinitions);
                routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
            }
        }
    }
}

这种将路由配置存储在数据库中的做法具有以下优势:

  1. 动态性:可以在不重启Gateway服务的情况下,实时更新路由配置。
  2. 灵活性:可以根据不同用户或角色,提供个性化的路由配置。
  3. 安全性:可以利用数据库的权限控制机制,实现更细粒度的访问控制。

值得注意的是,Spring Cloud Gateway支持多种路由匹配规则,包括但不限于Path、Method、Host、Query等。这些规则按照一定的优先级顺序进行匹配,具体顺序为:Cloud Foundry Route Service Route Predicate > Weight Route Predicate > Method Route Predicate > Path Route Predicate > Query Route Predicate > Header Route Predicate > Cookie Route Predicate > RemoteAddr Route Predicate > Host Route Predicate。

将路由配置存储在数据库中,不仅能够实现更灵活的动态管理,还能为微服务架构带来更大的灵活性和可扩展性。它使得我们可以根据业务需求的变化,快速调整API网关的路由策略,而无需频繁修改代码或重启服务。同时,这种做法也为实现更复杂的权限控制和流量管理提供了可能,有助于构建更加健壮和安全的微服务系统。