了解完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类,这里不在一一说明。
相关推荐
《Spring Cloud项目源码深度解析》 在当前的微服务架构领域,Spring Cloud以其强大的功能和易用性,成为开发者构建分布式系统的重要选择。本文将深入探讨基于Spring Cloud的项目源码,帮助读者理解其核心原理,提升...
### 一、SpringCloud简介与核心组件 #### 1.1 SpringCloud概述 SpringCloud是一套基于Spring Boot实现的微服务云应用开发工具集,它提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线...
《Spring Cloud配置源码解析与实战》 Spring Cloud作为微服务架构的重要组件,为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话...
本教程将从基础入手,逐步深入到源码解析,使读者能更深入地了解和运用Spring Cloud。 首先,我们从入门开始。Spring Cloud提供了一个快速构建分布式系统工具集,包括服务发现(Eureka)、配置中心(Config Server...
1. **SpringCloud源码解析**: SpringCloud的源码分析有助于开发者了解其实现机制,从而更好地定制和优化自己的服务。源码中包含了Eureka服务发现、Zuul边缘服务、Hystrix断路器、 Ribbon客户端负载均衡、Feign声明...
总的来说,通过尚硅谷的SpringCloud源码解析和思维导图,开发者不仅可以深入了解SpringCloud的运作原理,还能提升对微服务架构设计的理解,为实际项目开发提供有力的支持。同时,对源码的学习也有助于培养解决问题和...
《SpringCloud Config 源码解析与应用实践》 SpringCloud Config 是一个强大的微服务配置中心,它允许我们在运行时管理应用的配置,并且能够实时地推送到客户端。本篇文章将深入探讨 SpringCloud Config 的核心原理...
《SpringCloud源码解析——构建微服务架构的关键组件》 SpringCloud作为当今最热门的微服务框架之一,深受广大开发者喜爱。它集成了众多优秀的开源项目,为开发人员提供了便捷的微服务开发工具。本篇将围绕Spring...
《基于SpringCloud的电商平台源码解析》 在现代互联网应用开发中,微服务架构已经成为主流。Spring Cloud作为一套完整的微服务解决方案,为开发者提供了构建分布式系统所需的工具集合,包括服务发现、配置中心、...
本资源为新手提供了一个完整的SpringCloud入门项目,包括源码、SQL脚本和详细的开发文档,非常适合想要快速了解和学习SpringCloud的新手。 1. **SpringCloud简介** SpringCloud是基于SpringBoot构建的服务治理框架...
本篇文章将深入探讨“SpringCloud黑马商城后端代码”,解析其中的关键技术和实现细节。 首先,Spring Cloud是基于Spring Boot的一套微服务解决方案,它提供了服务注册与发现、配置中心、API网关、负载均衡、熔断器...
《基于SpringCloud的分布式网上商城系统源码解析》 在当今互联网时代,电子商务系统的复杂性和规模日益增大,传统的单体架构难以应对高并发、高可用的业务需求。为了解决这些问题,开发人员开始转向分布式系统架构...
本篇将深入探讨Spring Cloud的核心组件和原理,结合"springcloud学习源码-yuanma.zip"中的源码,为你带来一次全面的学习体验。 首先,我们来了解Spring Cloud的基础知识。Spring Cloud是基于Spring Boot的微服务...
《2020最新版SpringCloud(H版&alibaba)框架开发教程》是一套全面而深入的SpringCloud学习资源,涵盖了从基础到高级的各种技术点。这套教程旨在帮助开发者掌握SpringCloud的核心概念和实践技巧,尤其针对H版及阿里...
《SpringCloud微服务实战》这本书籍的源代码包含了大量的实践示例和配置,旨在帮助读者深入理解并掌握Spring Cloud在实际开发中的应用。Spring Cloud是一个基于Spring Boot实现的服务发现、配置管理和API网关等...
总的来说,这份"Spring Cloud.pdf"学习资料涵盖了Spring Cloud的基础知识、核心组件的使用、源码解析以及实战演示,对于想要深入学习和掌握Spring Cloud的开发者来说是一份宝贵的资源。通过系统学习并实践其中的示例...
源码解析可以帮助我们理解Zuul如何处理请求,以及过滤器链的执行流程。 3. **断路器** - Hystrix是Netflix开源的断路器库,用于防止服务雪崩。当服务调用失败或响应时间过长时,断路器会打开,避免后续请求继续失败...
1. 配置中心:可能使用了Spring Cloud Config来集中管理所有服务的配置,这样可以方便地在不同环境中切换配置。 2. 服务注册与发现:可能使用Eureka或Consul等服务注册与发现组件,确保服务之间的通信。 3. 安全配置...
《疯狂springCloud实战架构》是针对企业级分布式应用开发的一款强大框架——Spring Cloud的深度解析与实战指南。Spring Cloud作为微服务生态中的重要组件,它为开发者提供了在分布式系统(如配置管理、服务发现、...
断路器示意图 SpringCloud Netflix实现了断路器库的名字叫Hystrix. 在微服务架构下,通常会有多个层次的服务调用. 下面是微服架构下, 浏览器端通过API访问后台微服务的一个示意图: hystrix 1 一个微服务的超时...