当前位置:   article > 正文

Jenkins + NACOS + GATEWAY 实现微服务不停机部署

微服务不停机部署

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>
  1. gateway 服务配置

 在Nacos 管理端下线服务后,Nacos服务端有定时延迟机制导致不能及时更新状态,导致服务重启后gateway网关依然会把请求分配到已经下线且停机的服务,导致接口提示未找到服务

此时需要更改gateway服务配置,定制自己的监听事件

增加MySubscribeConfig配置文件

/resources/META-INF 下增加spring.factories配置文件,内容如下:

  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  2. com.daishu.gateway.config.MySubscribeConfig
  1. import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
  2. import com.alibaba.cloud.nacos.NacosServiceManager;
  3. import com.daishu.common.core.utils.SpringContextHolder;
  4. import com.daishu.gateway.config.loadbalancer.MyNacosEventListener;
  5. import com.daishu.gateway.config.loadbalancer.MyNacosSubscribe;
  6. import org.springframework.boot.autoconfigure.AutoConfigureAfter;
  7. import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheManager;
  8. import org.springframework.cloud.loadbalancer.config.LoadBalancerCacheAutoConfiguration;
  9. import org.springframework.context.annotation.Bean;
  10. import org.springframework.context.annotation.Configuration;
  11. import org.springframework.context.annotation.Import;
  12. /**
  13. * 首先订阅当前网关关注的服务
  14. * nacos服务更新通知,但是gateway有一套自己的服务缓存列表。每次接到通知更新不及时导致转发到已经下线的服务
  15. * gateway获取缓存参考:org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier
  16. * nacos订阅参考:com.alibaba.cloud.nacos.discovery.NacosWatch#start()
  17. *
  18. */
  19. @Configuration
  20. @Import(SpringContextHolder.class)
  21. @AutoConfigureAfter(LoadBalancerCacheAutoConfiguration.class)
  22. public class MySubscribeConfig {
  23. @Bean
  24. public MyNacosSubscribe getMyNacosSubscribe(NacosServiceManager nacosServiceManager, NacosDiscoveryProperties properties){
  25. LoadBalancerCacheManager cacheManager = SpringContextHolder.getBean(LoadBalancerCacheManager.class);
  26. return new MyNacosSubscribe(nacosServiceManager,properties,new MyNacosEventListener(cacheManager));
  27. }
  28. }

  1. import cn.hutool.core.collection.CollectionUtil;
  2. import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
  3. import com.alibaba.cloud.nacos.NacosServiceManager;
  4. import com.alibaba.nacos.api.naming.NamingService;
  5. import org.springframework.boot.ApplicationArguments;
  6. import org.springframework.boot.ApplicationRunner;
  7. import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
  8. import java.util.HashSet;
  9. import java.util.Set;
  10. /**
  11. * 订阅nacos推送更新事件
  12. * 启动和加载路由时重新订阅
  13. */
  14. public class MyNacosSubscribe implements ApplicationRunner {
  15. private NacosServiceManager nacosServiceManager;
  16. private NacosDiscoveryProperties properties;
  17. private MyNacosEventListener myEventListener;
  18. private Set<String> getRouteServices(){
  19. // 这里返回自己要订阅的服务名称
  20. Set<String> serviceName=new HashSet<>();
  21. serviceName.add("server-name");
  22. return serviceName;
  23. }
  24. // 这里监听时间是为了在路由信息修改时候,重新订阅服务的。如果说路由重新加载不会有订阅变动的话,可以去掉
  25. @org.springframework.context.event.EventListener({RefreshRoutesEvent.class})
  26. public void subscribe() {
  27. NamingService namingService = nacosServiceManager
  28. .getNamingService(properties.getNacosProperties());
  29. try {
  30. Set<String> services = getRouteServices();
  31. if(CollectionUtil.isNotEmpty(services)){
  32. for (String service : services) {
  33. namingService.subscribe(service, properties.getGroup(),
  34. null, myEventListener);
  35. }
  36. }
  37. } catch (Exception e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. @Override
  42. public void run(ApplicationArguments args) throws Exception {
  43. subscribe();
  44. }
  45. public MyNacosSubscribe(NacosServiceManager nacosServiceManager, NacosDiscoveryProperties properties, MyNacosEventListener myEventListener) {
  46. this.nacosServiceManager = nacosServiceManager;
  47. this.properties = properties;
  48. this.myEventListener = myEventListener;
  49. }

  1. import com.alibaba.cloud.nacos.discovery.NacosServiceDiscovery;
  2. import com.alibaba.nacos.api.naming.listener.Event;
  3. import com.alibaba.nacos.api.naming.listener.EventListener;
  4. import com.alibaba.nacos.api.naming.listener.NamingEvent;
  5. import com.alibaba.nacos.api.naming.pojo.Instance;
  6. import org.springframework.cache.Cache;
  7. import org.springframework.cloud.loadbalancer.cache.LoadBalancerCacheManager;
  8. import org.springframework.cloud.loadbalancer.core.CachingServiceInstanceListSupplier;
  9. import java.util.List;
  10. /**
  11. * 处理nacos推送更新事件
  12. */
  13. public class MyNacosEventListener implements EventListener {
  14. private LoadBalancerCacheManager loadBalancerCacheManager;
  15. @Override
  16. public void onEvent(Event event) {
  17. try {
  18. if (event instanceof NamingEvent) {
  19. Cache cache = loadBalancerCacheManager.getCache(CachingServiceInstanceListSupplier.SERVICE_INSTANCE_CACHE_NAME);
  20. if(cache!=null){
  21. NamingEvent namingEvent = ((NamingEvent) event);
  22. String serviceName = namingEvent.getServiceName();
  23. List<Instance> instances = namingEvent.getInstances();
  24. cache.put(serviceName, NacosServiceDiscovery.hostToServiceInstanceList(instances,serviceName));
  25. }
  26. }
  27. }catch (Exception e){
  28. e.printStackTrace();
  29. }
  30. }
  31. public MyNacosEventListener(LoadBalancerCacheManager loadBalancerCacheManager) {
  32. this.loadBalancerCacheManager = loadBalancerCacheManager;
  33. }
  34. }
  1. import lombok.extern.slf4j.Slf4j;
  2. import org.springframework.beans.factory.DisposableBean;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.ApplicationContextAware;
  5. import org.springframework.context.annotation.Lazy;
  6. /**
  7. * spring工具类
  8. */
  9. @Slf4j
  10. @Lazy(false)
  11. public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
  12. private static ApplicationContext applicationContext = null;
  13. @Override
  14. public void setApplicationContext(ApplicationContext applicationContext) {
  15. SpringContextHolder.applicationContext = applicationContext;
  16. }
  17. public static <T> T getBean(Class<T> requiredType) {
  18. return applicationContext.getBean(requiredType);
  19. }
  20. public static void clearHolder() {
  21. if (log.isDebugEnabled()) {
  22. log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
  23. }
  24. applicationContext = null;
  25. }
  26. @Override
  27. public void destroy() {
  28. SpringContextHolder.clearHolder();
  29. }
  30. }

配置好重启网关服务,naocs管理端修改服务下线状态,发现断点已经进入监听类即完成配置

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/745544
推荐阅读
相关标签
  

闽ICP备14008679号