-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Yingbo Wang
committed
Oct 18, 2022
1 parent
89e1b2e
commit abb2e65
Showing
16 changed files
with
1,141 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<parent> | ||
<artifactId>rms-mall</artifactId> | ||
<groupId>com.wyb.rms</groupId> | ||
<version>0.0.1-SNAPSHOT</version> | ||
</parent> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<artifactId>rms-mall-gateway</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
<packaging>jar</packaging> | ||
|
||
<!-- 模块名及描述信息 --> | ||
<name>e-rms-mall-gateway</name> | ||
<description>Spring Cloud Gateway</description> | ||
|
||
<properties> | ||
<maven.compiler.source>8</maven.compiler.source> | ||
<maven.compiler.target>8</maven.compiler.target> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.alibaba.cloud</groupId> | ||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.cloud</groupId> | ||
<artifactId>spring-cloud-starter-gateway</artifactId> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>com.wyb.rms</groupId> | ||
<artifactId>rms-mall-common</artifactId> | ||
<version>0.0.1-SNAPSHOT</version> | ||
</dependency> | ||
</dependencies> | ||
|
||
<!-- | ||
SpringBoot的Maven插件, 能够以Maven的方式为应用提供SpringBoot的支持,可以将 | ||
SpringBoot应用打包为可执行的jar或war文件, 然后以通常的方式运行SpringBoot应用 | ||
--> | ||
<build> | ||
<finalName>${artifactId}</finalName> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-maven-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>repackage</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
18 changes: 18 additions & 0 deletions
18
rms-mall-gateway/src/main/java/com/wyb/rms/gateway/GatewayApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.wyb.rms.gateway; | ||
|
||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; | ||
|
||
/** | ||
* <h1>网关启动入口</h1> | ||
* */ | ||
@EnableDiscoveryClient | ||
@SpringBootApplication | ||
public class GatewayApplication { | ||
|
||
public static void main(String[] args) { | ||
|
||
SpringApplication.run(GatewayApplication.class, args); | ||
} | ||
} |
121 changes: 121 additions & 0 deletions
121
rms-mall-gateway/src/main/java/com/wyb/rms/gateway/config/DynamicRouteServiceImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package com.wyb.rms.gateway.config; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import org.apache.commons.collections4.CollectionUtils; | ||
import org.springframework.cloud.gateway.event.RefreshRoutesEvent; | ||
import org.springframework.cloud.gateway.route.RouteDefinition; | ||
import org.springframework.cloud.gateway.route.RouteDefinitionLocator; | ||
import org.springframework.cloud.gateway.route.RouteDefinitionWriter; | ||
import org.springframework.context.ApplicationEventPublisher; | ||
import org.springframework.context.ApplicationEventPublisherAware; | ||
import org.springframework.stereotype.Service; | ||
import reactor.core.publisher.Mono; | ||
|
||
import java.util.List; | ||
|
||
/** | ||
* 事件推送 Aware: 动态更新路由网关 Service | ||
* */ | ||
@Slf4j | ||
@Service | ||
@SuppressWarnings("all") | ||
public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware { | ||
|
||
/** 写路由定义 */ | ||
private final RouteDefinitionWriter routeDefinitionWriter; | ||
/** 获取路由定义 */ | ||
private final RouteDefinitionLocator routeDefinitionLocator; | ||
|
||
/** 事件发布 */ | ||
private ApplicationEventPublisher publisher; | ||
|
||
public DynamicRouteServiceImpl(RouteDefinitionWriter routeDefinitionWriter, | ||
RouteDefinitionLocator routeDefinitionLocator) { | ||
this.routeDefinitionWriter = routeDefinitionWriter; | ||
this.routeDefinitionLocator = routeDefinitionLocator; | ||
} | ||
|
||
@Override | ||
public void setApplicationEventPublisher( | ||
ApplicationEventPublisher applicationEventPublisher) { | ||
// 完成事件推送句柄的初始化 | ||
this.publisher = applicationEventPublisher; | ||
} | ||
|
||
/** | ||
* <h2>增加路由定义</h2> | ||
* */ | ||
public String addRouteDefinition(RouteDefinition definition) { | ||
|
||
log.info("gateway add route: [{}]", definition); | ||
|
||
// 保存路由配置并发布 | ||
routeDefinitionWriter.save(Mono.just(definition)).subscribe(); | ||
// 发布事件通知给 Gateway, 同步新增的路由定义 | ||
this.publisher.publishEvent(new RefreshRoutesEvent(this)); | ||
|
||
return "success"; | ||
} | ||
|
||
/** | ||
* <h2>更新路由</h2> | ||
* */ | ||
public String updateList(List<RouteDefinition> definitions) { | ||
|
||
log.info("gateway update route: [{}]", definitions); | ||
|
||
// 先拿到当前 Gateway 中存储的路由定义 | ||
List<RouteDefinition> routeDefinitionsExits = | ||
routeDefinitionLocator.getRouteDefinitions().buffer().blockFirst(); | ||
if (!CollectionUtils.isEmpty(routeDefinitionsExits)) { | ||
// 清除掉之前所有的 "旧的" 路由定义 | ||
routeDefinitionsExits.forEach(rd -> { | ||
log.info("delete route definition: [{}]", rd); | ||
deleteById(rd.getId()); | ||
}); | ||
} | ||
|
||
// 把更新的路由定义同步到 gateway 中 | ||
definitions.forEach(definition -> updateByRouteDefinition(definition)); | ||
return "success"; | ||
} | ||
|
||
/** | ||
* <h2>根据路由 id 删除路由配置</h2> | ||
* */ | ||
private String deleteById(String id) { | ||
|
||
try { | ||
log.info("gateway delete route id: [{}]", id); | ||
this.routeDefinitionWriter.delete(Mono.just(id)).subscribe(); | ||
// 发布事件通知给 gateway 更新路由定义 | ||
this.publisher.publishEvent(new RefreshRoutesEvent(this)); | ||
return "delete success"; | ||
} catch (Exception ex) { | ||
log.error("gateway delete route fail: [{}]", ex.getMessage(), ex); | ||
return "delete fail"; | ||
} | ||
} | ||
|
||
/** | ||
* <h2>更新路由</h2> | ||
* 更新的实现策略比较简单: 删除 + 新增 = 更新 | ||
* */ | ||
private String updateByRouteDefinition(RouteDefinition definition) { | ||
|
||
try { | ||
log.info("gateway update route: [{}]", definition); | ||
this.routeDefinitionWriter.delete(Mono.just(definition.getId())); | ||
} catch (Exception ex) { | ||
return "update fail, not find route routeId: " + definition.getId(); | ||
} | ||
|
||
try { | ||
this.routeDefinitionWriter.save(Mono.just(definition)).subscribe(); | ||
this.publisher.publishEvent(new RefreshRoutesEvent(this)); | ||
return "success"; | ||
} catch (Exception ex) { | ||
return "update route fail"; | ||
} | ||
} | ||
} |
129 changes: 129 additions & 0 deletions
129
...mall-gateway/src/main/java/com/wyb/rms/gateway/config/DynamicRouteServiceImplByNacos.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package com.wyb.rms.gateway.config; | ||
|
||
import com.alibaba.fastjson.JSON; | ||
import com.alibaba.nacos.api.NacosFactory; | ||
import com.alibaba.nacos.api.config.ConfigService; | ||
import com.alibaba.nacos.api.config.listener.Listener; | ||
import com.alibaba.nacos.api.exception.NacosException; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.apache.commons.collections4.CollectionUtils; | ||
import org.springframework.cloud.gateway.route.RouteDefinition; | ||
import org.springframework.context.annotation.DependsOn; | ||
import org.springframework.stereotype.Component; | ||
|
||
import javax.annotation.PostConstruct; | ||
import java.util.List; | ||
import java.util.Properties; | ||
import java.util.concurrent.Executor; | ||
|
||
/** | ||
* <h1>通过 nacos 下发动态路由配置, 监听 Nacos 中路由配置变更</h1> | ||
* */ | ||
@Slf4j | ||
@Component | ||
@DependsOn({"gatewayConfig"}) | ||
public class DynamicRouteServiceImplByNacos { | ||
|
||
/** Nacos 配置服务 */ | ||
private ConfigService configService; | ||
private final DynamicRouteServiceImpl dynamicRouteService; | ||
|
||
public DynamicRouteServiceImplByNacos(DynamicRouteServiceImpl dynamicRouteService) { | ||
this.dynamicRouteService = dynamicRouteService; | ||
} | ||
|
||
/** | ||
* <h2>Bean 在容器中构造完成之后会执行 init 方法</h2> | ||
* */ | ||
@PostConstruct | ||
public void init() { | ||
|
||
log.info("gateway route init...."); | ||
|
||
try { | ||
// 初始化 Nacos 配置客户端 | ||
configService = initConfigService(); | ||
if (null == configService) { | ||
log.error("init config service fail"); | ||
return; | ||
} | ||
|
||
// 通过 Nacos Config 并指定路由配置路径去获取路由配置 | ||
String configInfo = configService.getConfig( | ||
GatewayConfig.NACOS_ROUTE_DATA_ID, | ||
GatewayConfig.NACOS_ROUTE_GROUP, | ||
GatewayConfig.DEFAULT_TIMEOUT | ||
); | ||
|
||
log.info("get current gateway config: [{}]", configInfo); | ||
List<RouteDefinition> definitionList = | ||
JSON.parseArray(configInfo, RouteDefinition.class); | ||
|
||
if (CollectionUtils.isNotEmpty(definitionList)) { | ||
for (RouteDefinition definition : definitionList) { | ||
log.info("init gateway config: [{}]", definition.toString()); | ||
dynamicRouteService.addRouteDefinition(definition); | ||
} | ||
} | ||
|
||
} catch (Exception ex) { | ||
log.error("gateway route init has some error: [{}]", ex.getMessage(), ex); | ||
} | ||
|
||
// 设置监听器 | ||
dynamicRouteByNacosListener(GatewayConfig.NACOS_ROUTE_DATA_ID, | ||
GatewayConfig.NACOS_ROUTE_GROUP); | ||
} | ||
|
||
/** | ||
* <h2>初始化 Nacos Config</h2> | ||
* */ | ||
private ConfigService initConfigService() { | ||
|
||
try { | ||
Properties properties = new Properties(); | ||
properties.setProperty("serverAddr", GatewayConfig.NACOS_SERVER_ADDR); | ||
properties.setProperty("namespace", GatewayConfig.NACOS_NAMESPACE); | ||
return configService = NacosFactory.createConfigService(properties); | ||
} catch (Exception ex) { | ||
log.error("init gateway nacos config error: [{}]", ex.getMessage(), ex); | ||
return null; | ||
} | ||
} | ||
|
||
/** | ||
* <h2>监听 Nacos 下发的动态路由配置</h2> | ||
* */ | ||
private void dynamicRouteByNacosListener(String dataId, String group) { | ||
|
||
try { | ||
// 给 Nacos Config 客户端增加一个监听器 | ||
configService.addListener(dataId, group, new Listener() { | ||
|
||
/** | ||
* <h2>自己提供线程池执行操作</h2> | ||
* */ | ||
@Override | ||
public Executor getExecutor() { | ||
return null; | ||
} | ||
|
||
/** | ||
* <h2>监听器收到配置更新</h2> | ||
* @param configInfo Nacos 中最新的配置定义 | ||
* */ | ||
@Override | ||
public void receiveConfigInfo(String configInfo) { | ||
|
||
log.info("start to update config: [{}]", configInfo); | ||
List<RouteDefinition> definitionList = | ||
JSON.parseArray(configInfo, RouteDefinition.class); | ||
log.info("update route: [{}]", definitionList.toString()); | ||
dynamicRouteService.updateList(definitionList); | ||
} | ||
}); | ||
} catch (NacosException ex) { | ||
log.error("dynamic update gateway config error: [{}]", ex.getMessage(), ex); | ||
} | ||
} | ||
} |
Oops, something went wrong.