通过gateway配合nacos做动态路由一共两种方式,第一种时通过json,解析json进行动态路由,另一种通过设置properties文件进行路由
一、通过解析json
gateway的动态路由可以配置在nacos的配置中心上,gateway启动的时候来读取配置,对各个请求进行路由
配置文件如下所示
server:
port:9537
spring:
application:
name: cloud-alibaba-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
config:
server-addr: localhost:8848
file-extension: json
group: DEFAULT_GROUP#nacos分组
gateway:#路由
discovery:
locator:
enabled:true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
management:
endpoints:
web:
exposure:
include: cloud-alibaba-gateway
1、新建配置类
package com.gateway.springcloud.config;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
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.context.annotation.Configuration;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;
/**
* 配置动态路由
*/
@Configuration
public class NacosDynamicRouteServiceimplements ApplicationEventPublisherAware {
private StringdataId ="cloud-alibaba-gateway";
private Stringgroup ="DEFAULT_GROUP";
@Value("${spring.cloud.nacos.config.server-addr}")
private StringserverAddr;
@Autowired
private RouteDefinitionWriterrouteDefinitionWriter;
private ApplicationEventPublisherapplicationEventPublisher;
private static final ListROUTE_LIST =new ArrayList<>();
@PostConstruct
public void dynamicRouteByNacosListener() {
try {
Properties properties =new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
ConfigService configService = NacosFactory.createConfigService(properties);
String config = configService.getConfig(dataId, group, 5000);
configService.addListener(dataId, group, new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
clearRoute();
try {
List gatewayRouteDefinitions = JSONObject.parseArray(configInfo, RouteDefinition.class);
for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
addRoute(routeDefinition);
}
publish();
}catch (Exception e) {
e.printStackTrace();
}
}
@Override
public ExecutorgetExecutor() {
return null;
}
});
}catch (NacosException e) {
e.printStackTrace();
}
}
private void clearRoute() {
for(String id :ROUTE_LIST) {
this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
}
ROUTE_LIST.clear();
}
private void addRoute(RouteDefinition definition) {
try {
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
ROUTE_LIST.add(definition.getId());
}catch (Exception e) {
e.printStackTrace();
}
}
private void publish() {
this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}
2、启动gateway网关
这一步一定要在nacos添加配置之前,因为配置类添加的监听如果nacos上的配置没有进行添加或者修改,网关是读不到配置的,因为他监听的是改变。
3、nacos添加配置
里面的name参数,gateway已经规定好了,不允许随意修改,值如下图所示。
二、通过properties配置文件
本方式不需要建配置类,原理就是通过配置中心直接把动态路由的配置读到配置文件中,首先新建properties文件,
server.port=9547
spring.application.name=cloud-alibaba-gatewayaa
spring.cloud.nacos.discovery.server-addr=localhost:8848
spring.cloud.nacos.config.server-addr=localhost:8848
spring.cloud.nacos.config.file-extension=properties
spring.cloud.nacos.config.group=DEFAULT_GROUP
spring.cloud.gateway.discovery.locator.enabled=true
进入nacos,新建配置
yml配置如下所示