gateway+nacos秒级上下线
spring cloud gateway和nacos是我们常用的组件,如果不做处理,服务启动或停止后在gateway上并不会立即上线或者下线。带来的问题就是,部署服务的时候,要把新的服务启动,等待gateway更新,再把老的服务下线,再次等待gateway更新,最后停止老服务。很麻烦,体验很差。
究其原因,大概率是gateway里对服务做了缓存,但是服务上下线后没有触发缓存的更新,直到gateway自己检查服务在线状态才更新了缓存。既然它没有更新,那就让它更新就行
1.版本说明
spring-boot版本: 2.3.12.RELEASE
spring-cloud版本: Hoxton.SR12
nacos版本: 2.2.9.RELEASE
解决过程中查了不少资料,能成功的不多,可能是版本不一样造成的。
2.在gateway创建服务监听者
在gateway里创建监听者,当服务上、下线时更新
ServiceListenerComponent.java
@Component
public class ServiceListenerComponent {
@Resource
private NacosDiscoveryProperties discoveryProperties;
@Resource
private NacosServiceDiscovery serviceDiscovery;
@Resource
private ServiceEventListener eventListener;
private volatile NamingService naming;
protected static volatile List<String> services = new ArrayList<>();
protected volatile long time = 30000;
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
public void init(){
try {
naming = discoveryProperties.namingServiceInstance();
services = serviceDiscovery.getServices();
services.forEach(this::addServiceListener);
new Thread(()->{
for (;;){
try {
Thread.sleep(time);
List<String> newServices = serviceDiscovery.getServices();
for (String service : newServices){
if (!services.contains(service)){
services.add(service);
addServiceListener(service);
}
}
}catch (Exception e){
logger.error("发生错误!", e);
}
}
}).start();
}catch (Exception e){
logger.error("发生错误!", e);
}
}
/**
* 新的服务添加监听
* @param serviceName
*/
public void addServiceListener(String serviceName){
try {
naming.subscribe(serviceName, eventListener);
}catch (Exception e){
logger.error("发生错误!", e);
}
}
}
ServiceEventListener.java
@Component
public class ServiceEventListener implements EventListener {
@Resource
private NamedContextFactory factory;
/**
* 监听服务的变更并销毁原有的服务列表
* @param event
*/
@Override
public void onEvent(Event event) {
if (event instanceof NamingEvent){
//销毁服务上下文
factory.destroy();
}
}
}