在使用spring config server服务的时候发现在启动之后的一段时间内控制台会抛出异常,spring admin监控爆红,控制台信息如下
--2024-06-26 20:38:59.615 - WARN 2944 --- [oundedElastic-7] o.s.c.c.s.e.JGitEnvironmentRepository : Error occured cloning to base directory.
-
org.eclipse.jgit.api.errors.TransportException: git@gitee.com:xxx/app-config.git: socket is not establishedat org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:254) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]at org.eclipse.jgit.api.CloneCommand.fetch(CloneCommand.java:306) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]at org.eclipse.jgit.api.CloneCommand.call(CloneCommand.java:200) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]
配置的 spring.cloud.config.server.git.uri=git@gitee.com:xxx/{application}-config.git
采用的是多微服务git仓库隔离的方式进行管理,但是我当前的集群中仅仅启动了spring cloud config server节点,并且集群中并不存在名字为app的服务,通过断点代码查询发现是actuate health功能导致的,在org.springframework.cloud.config.server.config.EnvironmentRepositoryConfiguration.ConfigServerActuatorConfiguration
根据配置spring.cloud.config.server.health.enabled
实例化了一个health bean,而该值在默认情况下为true
@ConditionalOnClass({AbstractHealthIndicator.class})@ConditionalOnProperty(value = {"spring.cloud.config.server.health.enabled"},matchIfMissing = true)protected static class ConfigServerActuatorConfiguration {protected ConfigServerActuatorConfiguration() {}@Beanpublic ConfigServerHealthIndicator configServerHealthIndicator(EnvironmentRepository repository) {return new ConfigServerHealthIndicator(repository);}}
ConfigServerHealthIndicator实现了HealthIndicator接口,在当前节点内,通过ScheduleTask的形式定期运行,它的health check如下
@Overrideprotected void doHealthCheck(Health.Builder builder) throws Exception {builder.up();List<Map<String, Object>> details = new ArrayList<>();for (String name : this.repositories.keySet()) {Repository repository = this.repositories.get(name);String application = (repository.getName() == null) ? name: repository.getName();String profiles = repository.getProfiles();try {Environment environment = this.environmentRepository.findOne(application,profiles, repository.getLabel(), false);HashMap<String, Object> detail = new HashMap<>();detail.put("name", environment.getName());detail.put("label", environment.getLabel());if (environment.getProfiles() != null&& environment.getProfiles().length > 0) {detail.put("profiles", Arrays.asList(environment.getProfiles()));}if (!CollectionUtils.isEmpty(environment.getPropertySources())) {List<String> sources = new ArrayList<>();for (PropertySource source : environment.getPropertySources()) {sources.add(source.getName());}detail.put("sources", sources);}details.add(detail);}catch (Exception e) {logger.debug("Could not read repository: " + application, e);HashMap<String, String> map = new HashMap<>();map.put("application", application);map.put("profiles", profiles);builder.withDetail("repository", map);builder.down(e);return;}}builder.withDetail("repositories", details);}@PostConstructpublic void init() {if (this.repositories.isEmpty()) {this.repositories.put("app", new Repository());}}
在bean 构造完成的时候会执行一个init方法,直接推了一个app 进去,这就是罪魁祸首,可以把spring.cloud.config.server.health.enabled
设置为false关闭health的检查或者配置一个spring.cloud.config.server.health.repositories
配置一个真实的应用比如
spring.cloud.config.server.health.repositories.fxdanmugw-config.label=master
spring.cloud.config.server.health.repositories.fxdanmugw-config.name=xxx
排查这个问题的时候还在好奇为什么spring会提供这种能力?不过一想,确实有存在的必要,比如仓库中提供的配置被不小心删除了,微服务那边自己本身有一套默认配置,默认配置也可以让微服务成功启动,但是提供的服务存在差异,此时从服务状态上是很难直接预警的,但是如果有这个能力之后,endpoint 就能提供对应监视仓库文件是否存在,且配合Grafana Prometheus 提供预警能力,另外config server完全可以给客户端提供配置服务,比如游戏的配置服务,还自带版本管理,是一个有效的使用场景
我明确的记得在使用单个固定的git仓库的时候这个配置点是可以正常进行health check的,为什么改为多项目单仓库隔离就会出问题?真是奇怪这个需要进一步探究,又或者在启动的时候直接吧app这个给移除?
对应的官方描述在这里 health_indicator