CloudRouteResourceLoader.java
4.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package com.diligrp.xtrade.gateway.route.impl;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.diligrp.xtrade.gateway.config.GatewayResourceLoaderConfiguration;
import com.diligrp.xtrade.gateway.exception.GatewayServiceException;
import com.diligrp.xtrade.gateway.route.DynamicRouteLoaderIntf;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.config.GatewayProperties;
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.ApplicationContext;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @Auther: miaoguoxin
* @Date: 2020/4/2 14:02
* @Description: 从云端配置中心加载
* {@link GatewayResourceLoaderConfiguration} 配置
*/
@Slf4j
public class CloudRouteResourceLoader implements DynamicRouteLoaderIntf {
/**标记当前gatewayproties的hash值,用于判断配置是否更新过*/
private static int gatewayPropertiesHash;
/**防止重复初始化的标记*/
private static final AtomicBoolean HAS_INIT = new AtomicBoolean(false);
private final static String GROUP = "DEFAULT_GROUP";
private final static String ROUTE_CONFIG_NAME = "route.properties";
@Value("${spring.application.name}")
private String applicationName;
@Value("${spring.profiles.active}")
private String activeProfile;
@Value("${spring.cloud.nacos.config.file-extension}")
private String fileType;
@Autowired
private ApplicationContext applicationContext;
@Resource
private RouteDefinitionWriter routeDefinitionWriter;
@Autowired
private ConfigService configService;
@Autowired
private GatewayProperties gatewayProperties;
@Override
public void init() {
if (HAS_INIT.compareAndSet(false, true)) {
this.loadRoutes();
//用来判断routes是否改变过,避免无效刷新
gatewayPropertiesHash = gatewayProperties.getRoutes().hashCode();
}
}
@Override
public void refreshApis() {
}
@Override
public void refreshRoutes() {
this.notifyRefreshRoutes();
}
/**
* 通过nacos配置中心监听配置变化,
* 完成路由资源装载
* @author miaoguoxin
* @date 2020/4/10
*/
private void loadRoutes() {
//只有放到标准的配置文件下,才能够成功刷新配置
String configFile = String.format("%s-%s.%s", applicationName, activeProfile, fileType);
try {
configService.getConfigAndSignListener(
ROUTE_CONFIG_NAME,
GROUP,
5000,
new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
Timer timer = new Timer(true);
TimerTask task = new TimerTask() {
@Override
public void run() {
notifyRefreshRoutes();
}
};
//由于属性刷新有延迟,这里延长点时间
timer.schedule(task, 5000);
}
@Override
public Executor getExecutor() {
return null;
}
});
} catch (NacosException e) {
throw new GatewayServiceException("load route resource failed", e);
}
}
private void notifyRefreshRoutes() {
synchronized (CloudRouteResourceLoader.this){
if (gatewayPropertiesHash == gatewayProperties.getRoutes().hashCode()) {
return;
}
List<RouteDefinition> routes = gatewayProperties.getRoutes();
routes.forEach(definition ->
routeDefinitionWriter.save(Mono.just(definition)).subscribe());
applicationContext.publishEvent(new RefreshRoutesEvent(this));
gatewayPropertiesHash = gatewayProperties.getRoutes().hashCode();
log.info("refresh route success");
}
}
}