基于Nacos实现Spring Cloud Gateway实现动态路由

基于Nacos实现Spring Cloud Gateway实现动态路由

简介

该文档主要介绍以Nacos为配置中心,实现Spring Cloud GateWay 实现动态路由的功能。Spring Cloud Gateway启动时候,就将路由配置和规则加载到内存里,无法做到不重启网关就可以动态的对应路由的配置和规则进行增加,修改和删除。通过nacos的配置下发的功能可以实现在不重启网关的情况下,实现动态路由。

集成

Spring Cloud GateWay集成

spring-cloud-starter-gateway:路由转发、请求过滤(权限校验、限流以及监控等)

spring-boot-starter-webflux:反应式Web框架

spring-boot-starter-actuator:监控系统健康

<code>   <dependency>

<groupid>org.springframework.cloud/<groupid>

<artifactid>spring-cloud-starter-gateway/<artifactid>

/<dependency>

<dependency>

<groupid>org.springframework.boot/<groupid>

<artifactid>spring-boot-starter-webflux/<artifactid>

/<dependency>

<dependency>


<groupid>org.springframework.boot/<groupid>

<artifactid>spring-boot-starter-actuator/<artifactid>

/<dependency>/<code>

Nacos集成

nacos-client:nacos客户端,现在用比较新的版本0.9.0

<code><dependency>

<groupid>com.alibaba.nacos/<groupid>

<artifactid>nacos-client/<artifactid>

<version>0.9.0/<version>

/<dependency>/<code>

动态路由

DynamicRouteServiceImpl:提供动态路由的基础方法,可通过获取bean操作该类的方法。该类提供新增路由、更新路由、删除路由,然后实现发布的功能。

<code>@Service

public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {

@Autowired

private RouteDefinitionWriter routeDefinitionWriter;

private ApplicationEventPublisher publisher;

/**

* 增加路由

* @param definition

* @return

*/

public String add(RouteDefinition definition) {

routeDefinitionWriter.save(Mono.just(definition)).subscribe();

this.publisher.publishEvent(new RefreshRoutesEvent(this));

return "success";

}

/**

* 更新路由

* @param definition

* @return

*/

public String update(RouteDefinition definition) {

try {

this.routeDefinitionWriter.delete(Mono.just(definition.getId()));

} catch (Exception e) {

return "update fail,not find route routeId: "+definition.getId();

}

try {

routeDefinitionWriter.save(Mono.just(definition)).subscribe();

this.publisher.publishEvent(new RefreshRoutesEvent(this));

return "success";

} catch (Exception e) {

return "update route fail";

}

}

/**

* 删除路由

* @param id

* @return

*/

public String delete(String id) {

try {

this.routeDefinitionWriter.delete(Mono.just(id));

return "delete success";

} catch (Exception e) {

e.printStackTrace();

return "delete fail";

}

}

@Override

public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {

this.publisher = applicationEventPublisher;

}

}

RouteDefinition: 提供路由实体类,主要有predicates匹配来自用户的请求,filters服务路由

@Validated

public class RouteDefinition {


@NotEmpty

private String id = UUID.randomUUID().toString();

@NotEmpty

@Valid

private List<predicatedefinition> predicates = new ArrayList<>();

@Valid

private List<filterdefinition> filters = new ArrayList<>();

@NotNull

private URI uri;

private int order = 0;

public RouteDefinition() {}

public RouteDefinition(String text) {

int eqIdx = text.indexOf("=");

if (eqIdx <= 0) {

throw new ValidationException("Unable to parse RouteDefinition text '" + text + "'" +

", must be of the form name=value");

}

setId(text.substring(0, eqIdx));

String[] args = tokenizeToStringArray(text.substring(eqIdx+1), ",");

setUri(URI.create(args[0]));

for (int i=1; i < args.length; i++) {

this.predicates.add(new PredicateDefinition(args[i]));

}

}

public String getId() {


return id;

}

public void setId(String id) {

this.id = id;

}

public List<predicatedefinition> getPredicates() {

return predicates;

}

public void setPredicates(List<predicatedefinition> predicates) {

this.predicates = predicates;

}

public List<filterdefinition> getFilters() {

return filters;

}

public void setFilters(List<filterdefinition> filters) {

this.filters = filters;

}

public URI getUri() {

return uri;

}

public void setUri(URI uri) {

this.uri = uri;

}

public int getOrder() {

return order;


}

public void setOrder(int order) {

this.order = order;

}

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

RouteDefinition routeDefinition = (RouteDefinition) o;

return Objects.equals(id, routeDefinition.id) &&

Objects.equals(predicates, routeDefinition.predicates) &&

Objects.equals(order, routeDefinition.order) &&

Objects.equals(uri, routeDefinition.uri);

}

@Override

public int hashCode() {

return Objects.hash(id, predicates, uri);

}

@Override

public String toString() {

return "RouteDefinition{" +

"id='" + id + '\\'' +

", predicates=" + predicates +

", filters=" + filters +

", uri=" + uri +


", order=" + order +

'}';

}

}/<filterdefinition>/<filterdefinition>/<predicatedefinition>/<predicatedefinition>/<filterdefinition>/<predicatedefinition>/<code>

RouteDefinition: 提供路由实体类,主要有predicates匹配来自用户的请求,filters服务路由

<code>@Validated

public class RouteDefinition {

@NotEmpty

private String id = UUID.randomUUID().toString();

@NotEmpty

@Valid

private List<predicatedefinition> predicates = new ArrayList<>();

@Valid

private List<filterdefinition> filters = new ArrayList<>();

@NotNull

private URI uri;

private int order = 0;

public RouteDefinition() {}

public RouteDefinition(String text) {

int eqIdx = text.indexOf("=");

if (eqIdx <= 0) {

throw new ValidationException("Unable to parse RouteDefinition text '" + text + "'" +

", must be of the form name=value");

}


setId(text.substring(0, eqIdx));

String[] args = tokenizeToStringArray(text.substring(eqIdx+1), ",");

setUri(URI.create(args[0]));

for (int i=1; i < args.length; i++) {

this.predicates.add(new PredicateDefinition(args[i]));

}

}

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public List<predicatedefinition> getPredicates() {

return predicates;

}

public void setPredicates(List<predicatedefinition> predicates) {

this.predicates = predicates;

}

public List<filterdefinition> getFilters() {

return filters;

}

public void setFilters(List<filterdefinition> filters) {

this.filters = filters;

}


public URI getUri() {

return uri;

}

public void setUri(URI uri) {

this.uri = uri;

}

public int getOrder() {

return order;

}

public void setOrder(int order) {

this.order = order;

}

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

RouteDefinition routeDefinition = (RouteDefinition) o;

return Objects.equals(id, routeDefinition.id) &&

Objects.equals(predicates, routeDefinition.predicates) &&

Objects.equals(order, routeDefinition.order) &&

Objects.equals(uri, routeDefinition.uri);

}

@Override

public int hashCode() {

return Objects.hash(id, predicates, uri);


}

@Override

public String toString() {

return "RouteDefinition{" +

"id='" + id + '\\'' +

", predicates=" + predicates +

", filters=" + filters +

", uri=" + uri +

", order=" + order +

'}';

}

}/<filterdefinition>/<filterdefinition>/<predicatedefinition>/<predicatedefinition>/<filterdefinition>/<predicatedefinition>/<code>

NacosGatewayProperties:自定义属性绑定值,可通过配置文件配置属性。

<code>@ConfigurationProperties(prefix="nacos", ignoreUnknownFields = true)

@Configuration

public class NacosGatewayProperties {

private String address;

private String dataId;

private String groupId;

private Long timeout;

public String getAddress() {

return address;

}

public void setAddress(String address) {


this.address = address;

}

public String getDataId() {

return dataId;

}

public void setDataId(String dataId) {

this.dataId = dataId;

}

public String getGroupId() {

return groupId;

}

public void setGroupId(String groupId) {

this.groupId = groupId;

}

public Long getTimeout() {

return timeout;

}

public void setTimeout(Long timeout) {

this.timeout = timeout;

}

}/<code>

DynamicRouteServiceImplByNacos: 实现runner,通过nacos下发动态路由配置

<code>@Component

public class DynamicRouteServiceImplByNacos implements CommandLineRunner{

@Autowired

private DynamicRouteServiceImpl dynamicRouteService;

@Autowired

private NacosGatewayProperties nacosGatewayProperties;

/**

* 监听Nacos Server下发的动态路由配置

* @param dataId

* @param group

*/

public void dynamicRouteByNacosListener (){

try {

ConfigService configService=NacosFactory.createConfigService(nacosGatewayProperties.getAddress());

String content = configService.getConfig(nacosGatewayProperties.getDataId(), nacosGatewayProperties.getGroupId(), nacosGatewayProperties.getTimeout());

System.out.println(content);

configService.addListener(nacosGatewayProperties.getDataId(), nacosGatewayProperties.getGroupId(), new Listener() {

@Override

public void receiveConfigInfo(String configInfo) {

List<routedefinition> list = JsonUtils.toList(configInfo, RouteDefinition.class);

list.forEach(definition->{

dynamicRouteService.update(definition);

});

}

@Override

public Executor getExecutor() {

return null;


}

});

} catch (NacosException e) {

e.printStackTrace();

}

}

@Override

public void run(String... args) throws Exception {

dynamicRouteByNacosListener();

}

}/<routedefinition>/<code>

nacos配置下发

nacos配置

<code>nacos:

address: 127.0.0.1:8848

data-id: dhap-gateway

group-id: AAA

timeout: 5000/<code>

nacos属性文件定义

新建dataID为

groupID为AAA

基于Nacos实现Spring Cloud Gateway实现动态路由

<code>[

{

"filters": [],

"id": "blog1",

"order": 0,

"predicates": [{

"args": {

"pattern": "/z"

},

"name": "Path"

}],

"uri": "https://blog.csdn.net/zhangchangbin123"

},

{

"filters": [],

"id": "blog1",

"order": 0,

"predicates": [{

"args": {

"pattern": "/c"

},

"name": "Path"

}],

"uri": "https://blog.csdn.net/zhangchangbin123"

}

]/<code>

查看路由信息

基于Nacos实现Spring Cloud Gateway实现动态路由

路由结果

基于Nacos实现Spring Cloud Gateway实现动态路由

基于Nacos实现Spring Cloud Gateway实现动态路由

转载自:https://blog.csdn.net/zhangchangbin123/article/details/89391981


分享到:


相關文章: