`
357029540
  • 浏览: 735669 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论
阅读更多

了解完spring.cloud.config.client模块的代码,现在来了解下spring.cloud.config.monitor模块的代码。通过spring.factories启动文件可用看到只配置了一个自动配置类EnvironmentMonitorAutoConfiguration,我我们来看下这个类。

 进入到EnvironmentMonitorAutoConfiguration类,通过头部的注解可以了解到它是一个配置类,并且只能运行在WebApplication环境,然后通过注解@Import引入了FileMonitorConfiguration类。

 进入到FileMonitorConfiguration类,可以看到它实现了SmartLifecycle和ResourceLoaderAware接口,从这2个接口中可以看到一个是用于生命周期的管理,一个是用于资源文件的加载。通过FileMonitorConfiguration这个类的注解可以了解到它定义了一个定时任务。

 首先看看FileMonitorConfiguration类实现的SmartLifecycle接口的start()方法

public synchronized void start() {
   if (!this.running) {
      this.directory = getFileRepo();
      if (this.directory != null && !this.directory.isEmpty()) {
         log.info("Monitoring for local config changes: " + this.directory);
         try {
            this.watcher = FileSystems.getDefault().newWatchService();
            for (Path path : this.directory) {
               walkDirectory(path);
            }
         }
         catch (IOException e) {
         }
      }
      else {
         log.info("Not monitoring for local config changes");
      }
      this.running = true;
   }
}

 在初始化的时候字段running状态为false的时候通过getFileRepo()方法获取Set集合的文件路径

private Set<Path> getFileRepo() {
   if (this.scmRepository != null) {
      try {

         Resource resource = this.resourceLoader.getResource(this.scmRepository.getUri());
         if (resource instanceof FileSystemResource) {
            return Collections.singleton(Paths.get(resource.getURI()));
         }
      }
      catch (IOException e) {
         log.error("Cannot resolve URI for path: " + this.scmRepository.getUri());
      }
   }
   if (this.nativeEnvironmentRepository != null) {
      Set<Path> paths = new LinkedHashSet<>();
      for (String path : this.nativeEnvironmentRepository.getSearchLocations()) {
         Resource resource = this.resourceLoader.getResource(path);
         if (resource.exists()) {
            try {
               paths.add(Paths.get(resource.getURI()));
            }
            catch (Exception e) {
               log.error("Cannot resolve URI for path: " + path);
            }
         }
      }
      return paths;
   }
   return null;
}

在getFileRepo()方法中,它是通过ResourceLoader去加载配置的服务地址,返回获取的Resource信息,如果本地环境nativeEnvironmentRepository不为空,则去本地环境加载路径值。获取到path路径的Set集合后通过 FileSystems.getDefault().newWatchService()定义一个WatchService的监控类,然后循环path路径的Set集合,通过walkDirectory()方法来添加对文件的监控信息,git的文件不需要。

在看EnvironmentMonitorAutoConfiguration类,它定义了一个PropertyPathEndpoint的bean,这个bean引入了Bus模块的相关配置,因为这个类要配合bus模块来应用,我们进入到PropertyPathEndpoint类,可以看到它是一个RestController的API类,可以通过spring.cloud.config.monitor.endpoint.path自定义访问路径,然后加上monitor路径进行访问,同时它实现了ApplicationEventPublisherAware接口用于事件发布,我们看下它的2个path路径,都是通过POST方式访问的,但是notifyByForm()方法定义了consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE的访问条件,最终也是调用notifyByPath()方法,我们看下该方法

@RequestMapping(method = RequestMethod.POST)
public Set<String> notifyByPath(@RequestHeader HttpHeaders headers,
      @RequestBody Map<String, Object> request) {
   PropertyPathNotification notification = this.extractor.extract(headers, request);
   if (notification != null) {

      Set<String> services = new LinkedHashSet<>();

      for (String path : notification.getPaths()) {
         services.addAll(guessServiceName(path));
      }
      if (this.applicationEventPublisher != null) {
         for (String service : services) {
            log.info("Refresh for: " + service);
            this.applicationEventPublisher
                  .publishEvent(new RefreshRemoteApplicationEvent(this,
                        this.busId, service));
         }
         return services;
      }

   }
   return Collections.emptySet();
}

 在notifyByPath()方法中,通过PropertyPathNotificationExtractor类的具体实现类去实现extract()方法,我们主要看下它的实现类BasePropertyPathNotificationExtractor类,这个类主要是用于git相关的解析,我们看下extract()方法

public PropertyPathNotification extract(MultiValueMap<String, String> headers,
        Map<String, Object> request) {
    if (requestBelongsToGitRepoManager(headers)) {
        if (request.get("commits") instanceof Collection) {
            Set<String> paths = new HashSet<>();
            @SuppressWarnings("unchecked")
            Collection<Map<String, Object>> commits = (Collection<Map<String, Object>>) request
                    .get("commits");
            addPaths( paths, commits );
            if (!paths.isEmpty()) {
                return new PropertyPathNotification(paths.toArray(new String[0]));
            }
        }
    }
    return null;
}

 在extract()方法中,首先是通过requestBelongsToGitRepoManager()方法判断是否包含特定的推送信息,这里我们以GithubPropertyPathNotificationExtractor为例

protected boolean requestBelongsToGitRepoManager(MultiValueMap<String, String> headers) {
    return "push".equals(headers.getFirst("X-Github-Event"));
}

 通过requestBelongsToGitRepoManager()方法判断头部中的X-Github-Event是否是push事件,然后获取request集合中的commits信息,将获取到的文件改变的推送路径加载到paths集合中,返回PropertyPathNotification对象。

   获取到PropertyPathNotification对象后,在PropertyPathEndpoint类的notifyByPath()方法中定义了一个services的LinkedHashSet集合,该services用来添加在PropertyPathNotification对象中获取到的path路径,我们看下guessServiceName()方法

private Set<String> guessServiceName(String path) {
   Set<String> services = new LinkedHashSet<>();
   if (path != null) {
      String stem = StringUtils
            .stripFilenameExtension(StringUtils.getFilename(StringUtils.cleanPath(path)));
      // TODO: correlate with service registry
      int index = stem.indexOf("-");
      while (index >= 0) {
         String name = stem.substring(0, index);
         String profile = stem.substring(index + 1);
         if ("application".equals(name)) {
            services.add("*:" + profile);
         }
         else if (!name.startsWith("application")) {
            services.add(name + ":" + profile);
         }
         index = stem.indexOf("-", index + 1);
      }
      String name = stem;
      if ("application".equals(name)) {
         services.add("*");
      }
      else if (!name.startsWith("application")) {
         services.add(name);
      }
   }
   return services;
}

在guessServiceName()方法中,首先对路径进行了消除获取到了字符串为stem的文件后缀的名字,然后通过一系列的判断对文件进行加*操作,用于事件发布的需要。退出guessServiceName()方法后,在PropertyPathEndpoint类的notifyByPath()方法中对services进行了事件的发布通过RefreshRemoteApplicationEvent事件。

  介绍完PropertyPathEndpoint类,我们在回头看看EnvironmentMonitorAutoConfiguration类中定义的static类PropertyPathNotificationExtractorConfiguration,在该类中定义了一系列的PropertyPathNotificationExtractor接口实现类,在这些类上面都定义了prefix的配置路径,默认上是都加载,具体可以参考前面提到的GithubPropertyPathNotificationExtractor类,这里不在一一说明。 

0
0
分享到:
评论

相关推荐

    基于spring cloud项目源码源码.rar

    《Spring Cloud项目源码深度解析》 在当前的微服务架构领域,Spring Cloud以其强大的功能和易用性,成为开发者构建分布式系统的重要选择。本文将深入探讨基于Spring Cloud的项目源码,帮助读者理解其核心原理,提升...

    尚硅谷SpringCloud视频 + 源码 百度网盘

    ### 一、SpringCloud简介与核心组件 #### 1.1 SpringCloud概述 SpringCloud是一套基于Spring Boot实现的微服务云应用开发工具集,它提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线...

    spring cloud 配置源码.zip

    《Spring Cloud配置源码解析与实战》 Spring Cloud作为微服务架构的重要组件,为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话...

    spring-cloud实战源码

    本教程将从基础入手,逐步深入到源码解析,使读者能更深入地了解和运用Spring Cloud。 首先,我们从入门开始。Spring Cloud提供了一个快速构建分布式系统工具集,包括服务发现(Eureka)、配置中心(Config Server...

    springcloud 源码+解读

    1. **SpringCloud源码解析**: SpringCloud的源码分析有助于开发者了解其实现机制,从而更好地定制和优化自己的服务。源码中包含了Eureka服务发现、Zuul边缘服务、Hystrix断路器、 Ribbon客户端负载均衡、Feign声明...

    尚硅谷SpringCloud的源码及思维导图

    总的来说,通过尚硅谷的SpringCloud源码解析和思维导图,开发者不仅可以深入了解SpringCloud的运作原理,还能提升对微服务架构设计的理解,为实际项目开发提供有力的支持。同时,对源码的学习也有助于培养解决问题和...

    springcloud-config-master.rar

    《SpringCloud Config 源码解析与应用实践》 SpringCloud Config 是一个强大的微服务配置中心,它允许我们在运行时管理应用的配置,并且能够实时地推送到客户端。本篇文章将深入探讨 SpringCloud Config 的核心原理...

    SpringCloud源码-01.zip

    《SpringCloud源码解析——构建微服务架构的关键组件》 SpringCloud作为当今最热门的微服务框架之一,深受广大开发者喜爱。它集成了众多优秀的开源项目,为开发人员提供了便捷的微服务开发工具。本篇将围绕Spring...

    基于springcloud的电商平台源码.zip

    《基于SpringCloud的电商平台源码解析》 在现代互联网应用开发中,微服务架构已经成为主流。Spring Cloud作为一套完整的微服务解决方案,为开发者提供了构建分布式系统所需的工具集合,包括服务发现、配置中心、...

    适合新手入门的springcloud完整项目资源,附带sql和详细的开发文档,可直接导入运行。

    本资源为新手提供了一个完整的SpringCloud入门项目,包括源码、SQL脚本和详细的开发文档,非常适合想要快速了解和学习SpringCloud的新手。 1. **SpringCloud简介** SpringCloud是基于SpringBoot构建的服务治理框架...

    SpringCloud黑马商城后端代码

    本篇文章将深入探讨“SpringCloud黑马商城后端代码”,解析其中的关键技术和实现细节。 首先,Spring Cloud是基于Spring Boot的一套微服务解决方案,它提供了服务注册与发现、配置中心、API网关、负载均衡、熔断器...

    基于springcloud的分布式网上商城系统源码.zip

    《基于SpringCloud的分布式网上商城系统源码解析》 在当今互联网时代,电子商务系统的复杂性和规模日益增大,传统的单体架构难以应对高并发、高可用的业务需求。为了解决这些问题,开发人员开始转向分布式系统架构...

    springcloud学习源码-yuanma.zip

    本篇将深入探讨Spring Cloud的核心组件和原理,结合"springcloud学习源码-yuanma.zip"中的源码,为你带来一次全面的学习体验。 首先,我们来了解Spring Cloud的基础知识。Spring Cloud是基于Spring Boot的微服务...

    2020最新版SpringCloud(H版&alibaba)框架开发教程全套完整版从入门到精通(41-80讲).rar

    《2020最新版SpringCloud(H版&alibaba)框架开发教程》是一套全面而深入的SpringCloud学习资源,涵盖了从基础到高级的各种技术点。这套教程旨在帮助开发者掌握SpringCloud的核心概念和实践技巧,尤其针对H版及阿里...

    <>源代码

    《SpringCloud微服务实战》这本书籍的源代码包含了大量的实践示例和配置,旨在帮助读者深入理解并掌握Spring Cloud在实际开发中的应用。Spring Cloud是一个基于Spring Boot实现的服务发现、配置管理和API网关等...

    springcloud的所有技能都在这里面了

    总的来说,这份"Spring Cloud.pdf"学习资料涵盖了Spring Cloud的基础知识、核心组件的使用、源码解析以及实战演示,对于想要深入学习和掌握Spring Cloud的开发者来说是一份宝贵的资源。通过系统学习并实践其中的示例...

    从零开始搭建SpringCloud第七节源码

    源码解析可以帮助我们理解Zuul如何处理请求,以及过滤器链的执行流程。 3. **断路器** - Hystrix是Netflix开源的断路器库,用于防止服务雪崩。当服务调用失败或响应时间过长时,断路器会打开,避免后续请求继续失败...

    spring cloud实战项目

    1. 配置中心:可能使用了Spring Cloud Config来集中管理所有服务的配置,这样可以方便地在不同环境中切换配置。 2. 服务注册与发现:可能使用Eureka或Consul等服务注册与发现组件,确保服务之间的通信。 3. 安全配置...

    疯狂springCloud实战架构

    《疯狂springCloud实战架构》是针对企业级分布式应用开发的一款强大框架——Spring Cloud的深度解析与实战指南。Spring Cloud作为微服务生态中的重要组件,它为开发者提供了在分布式系统(如配置管理、服务发现、...

    springCloud

    断路器示意图 SpringCloud Netflix实现了断路器库的名字叫Hystrix. 在微服务架构下,通常会有多个层次的服务调用. 下面是微服架构下, 浏览器端通过API访问后台微服务的一个示意图: hystrix 1 一个微服务的超时...

Global site tag (gtag.js) - Google Analytics