当前位置 : 主页 > 网络编程 > PHP >

【SpringCloud】实现动态网关路由-Nacos

来源:互联网 收集:自由互联 发布时间:2023-09-07
本文记录一下如何使用 Gateway 搭建网关服务,实现动态路由的,帮助大家学习如何快速搭建网关服务,了解路由相关配置。 1、JSON路由配置 [ { "predicates": [ { "args": { "pattern": "/csdn" }, "n


本文记录一下如何使用 Gateway 搭建网关服务,实现动态路由的,帮助大家学习如何快速搭建网关服务,了解路由相关配置。

1、JSON路由配置

[
{


"predicates": [
{
"args": {
"pattern": "/csdn"
},
"name": "Path"
}
]
}
]

如图

【SpringCloud】实现动态网关路由-Nacos_springcloud

2、配置路由存储方式

实现动态路由的关键是 RouteDefinitionRepository 接口,该接口存在一个默认实现InMemoryRouteDefinitionRepository,通过名字我们应该也知道,该实现是将配置文件中配置的信息加载到内存中。

为了更清楚处理过程及扩展,重写了 RouteDefinitionRepository 接口中的方法。

import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* 配置路由存储方式
*
* @author H.Yang
* @date 2022/10/14
*/
@Component
public class LocalRouteDefinitionRepository implements RouteDefinitionRepository {
public final Map<String, RouteDefinition> routes = new ConcurrentHashMap();

/**
* 请注意,此方法很重要,从redis取路由信息的方法,官方核心包要用,核心路由功能都是从redis取的
*
* @return
*/
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
return Flux.fromIterable(routes.values());
}

@Override
public Mono<Void> save(Mono<RouteDefinition> route) {
return route.flatMap(r -> {
routes.put(r.getId(), r);
return Mono.empty();
});

}

@Override
public Mono<Void> delete(Mono<String> routeId) {
return routeId.flatMap(id -> {
if (routes.containsKey(id)) {
routes.remove(id);
return Mono.empty();
}
return Mono.defer(() -> Mono.error(new NotFoundException("路由文件没有找到: " + routeId)));
});
}

public void clear() {
routes.clear();
}
}

3、动态路由实现

编写态路由实现类,实现 ApplicationEventPublisherAware 接口。

服务启动时加载初始化路由配置,当配置发生变化的时候通过已添加的监听器监听 nacos 配置文件内的路由变化实现动态路由的功能。

import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.annotation.NacosInjected;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.ConfigType;
import com.alibaba.nacos.api.config.annotation.NacosConfigListener;
import com.alibaba.nacos.api.config.listener.Listener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
* @author H.Yang
* @date 2022/10/16
*/
@Slf4j
@Component
public class NacosDynamicRouteService implements ApplicationEventPublisherAware, CommandLineRunner {

private ApplicationEventPublisher applicationEventPublisher;

@Autowired
private LocalRouteDefinitionRepository localRouteDefinitionRepository;
@Autowired
private NacosConfigProperties nacosConfigProperties;

@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}


@Override
public void run(String... args) throws Exception {
log.debug("启动时加载....");
ConfigService configService = NacosFactory.createConfigService(nacosConfigProperties.assembleConfigServiceProperties());
// 程序首次启动, 并加载初始化路由配置
String configInfo = configService.getConfig("gateway-router.json", nacosConfigProperties.getGroup(), 5000);

this.addRouteConfig(configInfo);

// 添加监听器监听nacos配置文件内的路由变化
configService.addListener("gateway-router.json", nacosConfigProperties.getGroup(), new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
log.debug("配置发生变化时加载....");

refreshRouteConfig(configInfo);
}

@Override
public Executor getExecutor() {
return null;
}
});

}

/**
* 刷新路由配置
*
* @param configInfo
*/
private void refreshRouteConfig(String configInfo) {
// 刷新配置时需要先清空缓存
localRouteDefinitionRepository.clear();

this.addRouteConfig(configInfo);
}


/**
* 添加路由
*
* @param configInfo
*/
private void addRouteConfig(String configInfo) {
log.debug("动态添加路由配置...");

List<RouteDefinition> routeDefinitions = JSONUtil.toList(configInfo, RouteDefinition.class);
for (RouteDefinition routeDefinition : routeDefinitions) {
// 添加路由
localRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe();
}

this.publish();

log.debug("动态配置路由加载完成 {}", JSONUtil.toJsonStr(routeDefinitions));
}


/**
* 发布
*/
public void publish() {
applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
}

}
上一篇:R基本操作
下一篇:没有了
网友评论