文章目录
- 目前我们的服务流量入口已统一由网关进行转发,路由信息定义在配置文件中,但是这种方式有一个缺点就是修改路由信息必须重启服务才能生效。网关作为支付全部流量的入口,需要保证其高可用,所以需要做到不重启服务而修改路由信息,现结合Nacos去实现配置动态路由,同时需要转发服务统一注册到Nacos注册中心,网关直接在注册中心中选择机器进行转发。下面介绍具体改造的代码。
- 如果要实现动态路由配置,主要需要做到2点, Nacos能够监听到客户端前台配置文件的修改; 将修改的配置文件变更新到网关路由中; 针对以上2点,我们需要通过代码来监听Nacos配置文件修改变化,同时利用Spring事件发布将配置文件变更信息动态刷新到路由配置表中,核心代码如下: @Component @Slf4j public class NacosDynamicRouteService implements ApplicationEventPublisherAware { @Value(“${spring.cloud.nacos.config.server-addr}”) private String serverAddr; @Value(“${nacos.group}”) private String group; @Value(“${nacos.dataId}”) private String routeConfigDataId; @Value(“${nacos.namespace}”) private String namespace; @Resource private RouteDefinitionWriter routeDefinitionWriter; private ApplicationEventPublisher applicationEventPublisher; private static final List ROUTE_LIST = new ArrayList<>(); @Override public void setApplicationEventPublisher(@NotNull ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } @PostConstruct public void dynamicRouteListener() { try { Properties properties = new Properties(); properties.put(“serverAddr”, serverAddr); properties.put(“namespace”, namespace); ConfigService configService = NacosFactory.createConfigService(properties); // 程序首次启动, 并加载初始化路由配置 String initConfigInfo = configService.getConfig(routeConfigDataId, group, 5000); addAndPublishBatchRoute(initConfigInfo); configService.addListener(routeConfigDataId, group, new Listener() { @Override public void receiveConfigInfo(String configInfo) { addAndPublishBatchRoute(configInfo); } @Override public Executor getExecutor() { return null; } }); } catch (Exception e) { e.printStackTrace(); } } /** * 批量 添加及发布 路由 * @param configInfo 配置文件字符串, 必须为json array格式 */ private void addAndPublishBatchRoute(String configInfo) { try { clearRoute(); List gatewayRouteDefinitions = JSONObject.parseArray(configInfo, RouteDefinition.class); for (RouteDefinition routeDefinition : gatewayRouteDefinitions) { addRoute(routeDefinition); } publish(); log.info(“>>>>>>>>>>>>>>>>>Nacos Dynamic config gateway route finished | {}”, JSON.toJSONString(gatewayRouteDefinitions)); } catch (Exception e) { e.printStackTrace(); } } /** * 清空所有路由 */ private void clearRoute() { for(String id : ROUTE_LIST) { this.routeDefinitionWriter.delete(Mono.just(id)).subscribe(); } ROUTE_LIST.clear(); } /** * 添加单条路由信息 * @param definition RouteDefinition */ private void addRoute(RouteDefinition definition) { routeDefinitionWriter.save(Mono.just(definition)).subscribe(); ROUTE_LIST.add(definition.getId()); } /** * 发布路由表变更事件 */ private void publish() { this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter)); } } 配置文件yml nacos: group: DEFAULT_GROUP dataId: gateway-outer-nacos-beta namespace: beta
- 路由转发JSON 具体JSON配置如下:注意my-service为转发服务注册到Nacos的服务名 [{ “id”: “service”, “order”: 0, “predicates”: [{ “args”: { “pattern”: “/service/**” }, “name”: “Path” }], “filters”:[{ “args”: { “_genkey_0”: “1” }, “name”: “StripPrefix” }], “uri”: “lb://my-service” }]
- 第一步:引入Nacos注册中心和spring-cloud依赖 2.1.4.RELEASE com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config ${alibaba.nacos.version} com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery ${alibaba.nacos.version} org.springframework.cloud spring-cloud-dependencies Greenwich.SR6 pom import 第二步:SpringBootApplication增加服务发现注解 @EnableDiscoveryClient @SpringBootApplication @EnableDiscoveryClient public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } 第三步:增加bootstrap.yml 注册服务中心名称,网关负载转发 spring: application: name: my-service 第四步:配置文件增加Nacos注册中心配置地址 http://192.168.x.1:8848/nacos/index.html 为后台登陆管理界面 spring: cloud: nacos: config: server-addr: 192.168.x.1:8848,192.168.x.2:8848,192.168.x.3:8848 namespace: beta # 命名空间进行环境隔离 discovery: server-addr: 192.168.x.1:8848,192.168.x.2:8848,192.168.x.3:8848 namespace: beta # 命名空间进行环境隔离
- 首先,需要在网关项目增加负载均衡策略,权重设置才会生效,代码如下: @Configuration public class Configuration { @Bean @Scope(value=”prototype”) public IRule loadBalanceRule(){ return new NacosRule(); } } 接下来就可以在Nacos控制台界面进行权重设置,完成流量倾斜转发了。 注册服务列表 服务详情操作页 服务流量转发权重设置 在服务滚动发布过程中,可以通过点击服务下线按钮,停止正在上线服务的转发,避免因服务重启造成的数据问题。以上就是网关(SpringCloud Gateway)结合Nacos完成网关路由动态配置、灰度发布、服务优雅上下线等功能。 不断分享开发过程用到的技术和面试经常被问到的问题,如果您也对IT技术比较感兴趣可以「关注」我,让我们共同学习,共同进步!
随着业务和架构的发展,微服务的开发部署方式已经变成了如今技术发展的趋势,而在微服务流量入口控制上基本都是通过网关来实现的。网关的作用:路由转发、熔断、限流、安全认证、日志监控等,在前面也发布过一篇关于的文章,大家感兴趣的话可以去了解下网关的基本介绍。
目前我们的服务流量入口已统一由网关进行转发,路由信息定义在配置文件中,但是这种方式有一个缺点就是修改路由信息必须重启服务才能生效。网关作为支付全部流量的入口,需要保证其高可用,所以需要做到不重启服务而修改路由信息,现结合Nacos去实现配置动态路由,同时需要转发服务统一注册到Nacos注册中心,网关直接在注册中心中选择机器进行转发。下面介绍具体改造的代码。
如果要实现动态路由配置,主要需要做到2点,
- Nacos能够监听到客户端前台配置文件的修改;
- 将修改的配置文件变更新到网关路由中;
针对以上2点,我们需要通过代码来监听Nacos配置文件修改变化,同时利用Spring事件发布将配置文件变更信息动态刷新到路由配置表中,核心代码如下:
@Component
@Slf4j
public class NacosDynamicRouteService implements ApplicationEventPublisherAware {
@Value("${spring.cloud.nacos.config.server-addr}")
private String serverAddr;
@Value("${nacos.group}")
private String group;
@Value("${nacos.dataId}")
private String routeConfigDataId;
@Value("${nacos.namespace}")
private String namespace;
@Resource
private RouteDefinitionWriter routeDefinitionWriter;
private ApplicationEventPublisher applicationEventPublisher;
private static final List ROUTE_LIST = new ArrayList<>();
@Override
public void setApplicationEventPublisher(@NotNull ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
@PostConstruct
public void dynamicRouteListener() {
try {
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);
properties.put("namespace", namespace);
ConfigService configService = NacosFactory.createConfigService(properties);
// 程序首次启动, 并加载初始化路由配置
String initConfigInfo = configService.getConfig(routeConfigDataId, group, 5000);
addAndPublishBatchRoute(initConfigInfo);
configService.addListener(routeConfigDataId, group, new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
addAndPublishBatchRoute(configInfo);
}
@Override
public Executor getExecutor() {
return null;
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 批量 添加及发布 路由
* @param configInfo 配置文件字符串, 必须为json array格式
*/
private void addAndPublishBatchRoute(String configInfo) {
try {
clearRoute();
List gatewayRouteDefinitions = JSONObject.parseArray(configInfo, RouteDefinition.class);
for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
addRoute(routeDefinition);
}
publish();
log.info(">>>>>>>>>>>>>>>>>Nacos Dynamic config gateway route finished | {}", JSON.toJSONString(gatewayRouteDefinitions));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 清空所有路由
*/
private void clearRoute() {
for(String id : ROUTE_LIST) {
this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
}
ROUTE_LIST.clear();
}
/**
* 添加单条路由信息
* @param definition RouteDefinition
*/
private void addRoute(RouteDefinition definition) {
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
ROUTE_LIST.add(definition.getId());
}
/**
* 发布路由表变更事件
*/
private void publish() {
this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this.routeDefinitionWriter));
}
}
配置文件yml
nacos:
group: DEFAULT_GROUP
dataId: gateway-outer-nacos-beta
namespace: beta

路由转发JSON
具体JSON配置如下:注意my-service为转发服务注册到Nacos的服务名
[{
"id": "service",
"order": 0,
"predicates": [{
"args": {
"pattern": "/service/**"
},
"name": "Path"
}],
"filters":[{
"args": {
"_genkey_0": "1"
},
"name": "StripPrefix"
}],
"uri": "lb://my-service"
}]
第一步:引入Nacos注册中心和spring-cloud依赖
2.1.4.RELEASE
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
${alibaba.nacos.version}
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
${alibaba.nacos.version}
org.springframework.cloud
spring-cloud-dependencies
Greenwich.SR6
pom
import
第二步:SpringBootApplication增加服务发现注解 @EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
第三步:增加bootstrap.yml 注册服务中心名称,网关负载转发
spring:
application:
name: my-service
第四步:配置文件增加Nacos注册中心配置地址
http://192.168.x.1:8848/nacos/index.html 为后台登陆管理界面
spring:
cloud:
nacos:
config:
server-addr: 192.168.x.1:8848,192.168.x.2:8848,192.168.x.3:8848
namespace: beta # 命名空间进行环境隔离
discovery:
server-addr: 192.168.x.1:8848,192.168.x.2:8848,192.168.x.3:8848
namespace: beta # 命名空间进行环境隔离
首先,需要在网关项目增加负载均衡策略,权重设置才会生效,代码如下:
@Configuration
public class Configuration {
@Bean
@Scope(value="prototype")
public IRule loadBalanceRule(){
return new NacosRule();
}
}
接下来就可以在Nacos控制台界面进行权重设置,完成流量倾斜转发了。

注册服务列表

服务详情操作页

服务流量转发权重设置
在服务滚动发布过程中,可以通过点击服务下线按钮,停止正在上线服务的转发,避免因服务重启造成的数据问题。以上就是网关(SpringCloud Gateway)结合Nacos完成网关路由动态配置、灰度发布、服务优雅上下线等功能。
不断分享开发过程用到的技术和面试经常被问到的问题,如果您也对IT技术比较感兴趣可以「关注」我,让我们共同学习,共同进步!
发表回复