基於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


分享到:


相關文章: