赞
踩
Nacos 版本
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
Gateway 版本
<groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> <version>3.1.1</version>
在Nacos 管理端下线服务后,Nacos服务端有定时延迟机制导致不能及时更新状态,导致服务重启后gateway网关依然会把请求分配到已经下线且停机的服务,导致接口提示未找到服务
此时需要更改gateway服务配置,定制自己的监听事件
增加MySubscribeConfig配置文件
/resources/META-INF 下增加spring.factories配置文件,内容如下:
- org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- com.daishu.gateway.config.MySubscribeConfig
-
-
- import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
- import com.alibaba.cloud.nacos.NacosServiceManager;
- import com.daishu.common.core.utils.SpringContextHolder;
- import com.daishu.gateway.config.loadbalancer.MyNacosEventListener;
- import com.daishu.gateway.config.loadbalancer.MyNacosSubscribe;
- import org.springframework.boot.autoconfigure.AutoConfigureAfter;
- import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheManager;
- import org.springframework.cloud.loadbalancer.config.LoadBalancerCacheAutoConfiguration;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.Import;
-
-
- /**
- * 首先订阅当前网关关注的服务
- * nacos服务更新通知,但是gateway有一套自己的服务缓存列表。每次接到通知更新不及时导致转发到已经下线的服务
- * gateway获取缓存参考:org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier
- * nacos订阅参考:com.alibaba.cloud.nacos.discovery.NacosWatch#start()
- *
- */
- @Configuration
- @Import(SpringContextHolder.class)
- @AutoConfigureAfter(LoadBalancerCacheAutoConfiguration.class)
- public class MySubscribeConfig {
-
- @Bean
- public MyNacosSubscribe getMyNacosSubscribe(NacosServiceManager nacosServiceManager, NacosDiscoveryProperties properties){
- LoadBalancerCacheManager cacheManager = SpringContextHolder.getBean(LoadBalancerCacheManager.class);
- return new MyNacosSubscribe(nacosServiceManager,properties,new MyNacosEventListener(cacheManager));
- }
- }

-
- import cn.hutool.core.collection.CollectionUtil;
- import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
- import com.alibaba.cloud.nacos.NacosServiceManager;
- import com.alibaba.nacos.api.naming.NamingService;
- import org.springframework.boot.ApplicationArguments;
- import org.springframework.boot.ApplicationRunner;
- import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
-
- import java.util.HashSet;
- import java.util.Set;
-
- /**
- * 订阅nacos推送更新事件
- * 启动和加载路由时重新订阅
- */
- public class MyNacosSubscribe implements ApplicationRunner {
- private NacosServiceManager nacosServiceManager;
- private NacosDiscoveryProperties properties;
- private MyNacosEventListener myEventListener;
-
- private Set<String> getRouteServices(){
- // 这里返回自己要订阅的服务名称
- Set<String> serviceName=new HashSet<>();
- serviceName.add("server-name");
- return serviceName;
- }
- // 这里监听时间是为了在路由信息修改时候,重新订阅服务的。如果说路由重新加载不会有订阅变动的话,可以去掉
- @org.springframework.context.event.EventListener({RefreshRoutesEvent.class})
- public void subscribe() {
- NamingService namingService = nacosServiceManager
- .getNamingService(properties.getNacosProperties());
- try {
- Set<String> services = getRouteServices();
- if(CollectionUtil.isNotEmpty(services)){
- for (String service : services) {
- namingService.subscribe(service, properties.getGroup(),
- null, myEventListener);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void run(ApplicationArguments args) throws Exception {
- subscribe();
- }
-
- public MyNacosSubscribe(NacosServiceManager nacosServiceManager, NacosDiscoveryProperties properties, MyNacosEventListener myEventListener) {
- this.nacosServiceManager = nacosServiceManager;
- this.properties = properties;
- this.myEventListener = myEventListener;
- }

-
- import com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery;
- import com.alibaba.nacos.api.naming.listener.Event;
- import com.alibaba.nacos.api.naming.listener.EventListener;
- import com.alibaba.nacos.api.naming.listener.NamingEvent;
- import com.alibaba.nacos.api.naming.pojo.Instance;
- import org.springframework.cache.Cache;
- import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheManager;
- import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
-
- import java.util.List;
-
- /**
- * 处理nacos推送更新事件
- */
- public class MyNacosEventListener implements EventListener {
-
- private LoadBalancerCacheManager loadBalancerCacheManager;
- @Override
- public void onEvent(Event event) {
- try {
- if (event instanceof NamingEvent) {
- Cache cache = loadBalancerCacheManager.getCache(CachingServiceInstanceListSupplier.SERVICE_INSTANCE_CACHE_NAME);
- if(cache!=null){
- NamingEvent namingEvent = ((NamingEvent) event);
- String serviceName = namingEvent.getServiceName();
- List<Instance> instances = namingEvent.getInstances();
- cache.put(serviceName, NacosServiceDiscovery.hostToServiceInstanceList(instances,serviceName));
- }
- }
- }catch (Exception e){
- e.printStackTrace();
- }
- }
-
- public MyNacosEventListener(LoadBalancerCacheManager loadBalancerCacheManager) {
- this.loadBalancerCacheManager = loadBalancerCacheManager;
- }
- }

-
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.DisposableBean;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.ApplicationContextAware;
- import org.springframework.context.annotation.Lazy;
-
- /**
- * spring工具类
- */
- @Slf4j
- @Lazy(false)
- public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
-
- private static ApplicationContext applicationContext = null;
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) {
- SpringContextHolder.applicationContext = applicationContext;
- }
-
- public static <T> T getBean(Class<T> requiredType) {
- return applicationContext.getBean(requiredType);
- }
-
- public static void clearHolder() {
- if (log.isDebugEnabled()) {
- log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
- }
- applicationContext = null;
- }
-
-
- @Override
- public void destroy() {
- SpringContextHolder.clearHolder();
- }
-
-
- }

配置好重启网关服务,naocs管理端修改服务下线状态,发现断点已经进入监听类即完成配置
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。