springcloud线上一个问题,当config-server连不上git时,微服务集群慢慢的都挂掉。

在入口层增加了日志跟踪问题:

org.springframework.cloud.config.server.environment.EnvironmentController.java

    @RequestMapping("/{name}/{profiles}/{label:.*}")
public Environment labelled(@PathVariable String name, @PathVariable String profiles,
@PathVariable String label) {
if (name != null && name.contains("(_)")) {
// "(_)" is uncommon in a git repo name, but "/" cannot be matched
// by Spring MVC
name = name.replace("(_)", "/");
}
if (label != null && label.contains("(_)")) {
// "(_)" is uncommon in a git branch name, but "/" cannot be matched
// by Spring MVC
label = label.replace("(_)", "/");
}
StopWatch sw = new StopWatch("labelled");
sw.start();
logger.info("EnvironmentController.labelled()开始,name={},profiles={},label={}", name, profiles, label);
Environment environment = this.repository.findOne(name, profiles, label);
sw.stop();
logger.info("EnvironmentController.labelled()结束,name={},profiles={},label={},耗时={}毫秒,耗时={}秒", name, profiles, label, sw.getTotalTimeMillis(), sw.getTotalTimeSeconds());
return environment;
}

健康检查的入口ConfigServerHealthIndicator.java增加日志:

@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
StopWatch sw = new StopWatch("doHealthCheck");
sw.start();
logger.info("ConfigServerHealthIndicator.doHealthCheck()开始,builder={}", builder);
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()); 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) {
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);
sw.stop();
logger.info("ConfigServerHealthIndicator.doHealthCheck()结束,耗时={}毫秒,耗时={}秒,builder={}", sw.getTotalTimeMillis(), sw.getTotalTimeSeconds(), builder);
}

通过耗时统计的日志分析后,发现是EnvironmentController和ConfigServerHealthIndicator调用次数太多,这两个调用最终会调用JGitEnvironmentRepository.fetch()方法,这个fetch方法会去请求git,超时时间大概是5秒。

由于请求的数量过多,服务请求不过来,线程阻塞了很长时间。

分析:

1、EnvironmentController的调用是每个微服务模块发起的,为什么?

2、ConfigServerHealthIndicator的调用是config-server的健康检查,可以通过设置检查的间隔时间缓解问题。

    consul:
host: 10.200.110.100
port: 8500
enabled: true
discovery:
enabled: true
hostname: 10.200.110.100
healthCheckInterval: 30s
queryPassing: true

EnvironmentController的请求时用config-server的client端的健康检查发起的调用。看源码:

各个客户端在连接注册中心,获取到配置中心实例后,会调用上面这段代码逻辑从配置中心获取到 Environment数据变量,上线环境后,遇到了一个问题,查看日志,发现这块逻辑被不停的调用,每20多秒就会调用一次,application的name为 app,通过查看SpringCloudConfig的官方文档知道Config Server 通过一个健康指示器来检测配置的EnvironmentRepository是否正常工作。 默认情况下会向EnvironmentRepository询问一个名字为app的应用配置,EnvironmentRepository实例回应default配置。   也就是说当健康监视器默认开启的时候,会不停的调用findOne来检测,配置是否可用,是否会出现异常,

这段代码是org.springframework.cloud.config.server.config.ConfigServerHealthIndicator类里初始化名称为application名字为app的代码

@ConfigurationProperties("spring.cloud.config.server.health")
public class ConfigServerHealthIndicator extends AbstractHealthIndicator { private EnvironmentRepository environmentRepository; private Map<String, Repository> repositories = new LinkedHashMap<>(); public ConfigServerHealthIndicator(EnvironmentRepository environmentRepository) {
this.environmentRepository = environmentRepository;
} @PostConstruct
public void init() {
if (this.repositories.isEmpty()) {
this.repositories.put("app", new Repository());
}
}
//...
}

如果想停止掉这样的检测可以通过配置health.config.enabled=false去关闭此功能。

看源码:org.springframework.cloud.config.client.ConfigClientAutoConfiguration.java

@Configuration
public class ConfigClientAutoConfiguration {
@Configuration
@ConditionalOnClass(HealthIndicator.class)
@ConditionalOnBean(ConfigServicePropertySourceLocator.class)
@ConditionalOnProperty(value = "health.config.enabled", matchIfMissing = true)
protected static class ConfigServerHealthIndicatorConfiguration { @Bean
public ConfigServerHealthIndicator configServerHealthIndicator(
ConfigServicePropertySourceLocator locator,
ConfigClientHealthProperties properties, Environment environment) {
return new ConfigServerHealthIndicator(locator, environment, properties);
}
}
//...

Spring Cloud config之三:config-server因为server端和client端的健康检查导致服务超时阻塞问题的更多相关文章

  1. Spring Cloud 入门 之 Config 篇(六)

    原文地址:Spring Cloud 入门 之 Config 篇(六) 博客地址:http://www.extlight.com 一.前言 随着业务的扩展,为了方便开发和维护项目,我们通常会将大项目拆分 ...

  2. Spring Cloud 系列之 Config 配置中心(三)

    本篇文章为系列文章,未读前几集的同学请猛戳这里: Spring Cloud 系列之 Config 配置中心(一) Spring Cloud 系列之 Config 配置中心(二) 本篇文章讲解 Conf ...

  3. Spring Cloud Alibaba Nacos Config 实战

    Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持.使用 Spring Cloud Alibaba Nacos Config,您可 ...

  4. Spring Cloud 系列之 Config 配置中心(二)

    本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Config 配置中心(一) 本篇文章讲解 Config 如何实现配置中心自动刷新. 配置中心自动刷新 点击链接观看: ...

  5. Spring Cloud Alibaba Nacos Config 的使用

    Spring Cloud Alibaba Nacos Config 的使用 一.需求 二.实现功能 1.加载 product-provider-dev.yaml 配置文件 2.实现配置的自动刷新 3. ...

  6. spring cloud provider报“Error parsing HTTP request header”,feign端报“Read timed out“

    这两天在调试spring cloud feign+hystrix报了如下错误: spring cloud provider报“Error parsing HTTP request header”,fe ...

  7. 在socket的server端处理client端发来的数据

    一.楔子 最近做了一个需求遇到一个坑,归结成一个小问题,其实就是在socket的server端处理client端发来的数据的问题,现将这个问题总结一下,本文将数据在server端以字典的形式存储. 另 ...

  8. 用同一台PC的两个网口实现Iperf的server端和client端

    用同一台PC的两个网口实现Iperf的server端和client端 2015年10月20日 20:35:11 阅读数:2943 有时候需要发包,仅仅需要一定速率的流量,并不需要关心收到报文的大小,一 ...

  9. spring cloud 学习(5) - config server

    分布式环境下的统一配置框架,已经有不少了,比如百度的disconf,阿里的diamand.今天来看下spring cloud对应的解决方案: 如上图,从架构上就可以看出与disconf之类的有很大不同 ...

随机推荐

  1. python数据分析三剑客之: matplotlib绘图模块

    matplotlib 一.Matplotlib基础知识 Matplotlib中的基本图表包括的元素 - x轴和y轴 axis 水平和垂直的轴线 - x轴和y轴刻度 tick 刻度标示坐标轴的分隔,包括 ...

  2. 【python+selenium学习】Python常见错误之:IndentationError: unexpected indent

    初入python+selenium学习之路,总会遇到这样那样的问题.IndentationError: unexpected indent,这个坑我已经踏进数次了,索性记录下来.都知道Python对代 ...

  3. git分支的衍合

    一般我们使用衍合的目的,是想要得到一个能在远程分支上干净应用的补丁 — 比如某些项目你不是维护者,但想帮点忙的话,最好用衍合:先在自己的一个分支里进行开发,当准备向主项目提交补丁的时候,根据最新的 o ...

  4. Js中replace替换所有*

    var t = '***感**谢**有**你***'; var r = t.replace(/\*/g,''); //\为转义字符 g表示全局 console.log(r) //感谢有你

  5. Mysql-修改用户连接数据库IP地址和用户名

    将用户连接数据库(5.7.14-7)的IP地址从 10.10.5.16   修改为 10.11.4.197 Mysql> rename user 'username'@'10.10.5.16' ...

  6. 创建readonly只读用户脚本

    身为一名运维工作人员,保证服务器的安全是必要项,当开发人员或测试人员需登录到服务器查看日志等操作时,可只给定特定的权限防止误操作的惨况产生. 以下脚本内容均为我本人环境,如有更改可自行修改. ~]# ...

  7. Linux服务之DNS介绍

    DNS-------Domain Name System域名系统 介绍:DNS就是把域名和IP地址联系在一起的服务,有了DNS服务器,你就不用输入IP地址来访问一个网站,可以通过输入网址访问.     ...

  8. Linux操作系统安全-加密和安全扫盲篇

    Linux操作系统安全-加密和安全 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.墨菲定律 墨菲定律: 一种心理学效应,是由爱德华·墨菲(Edward A. Murphy)提出 ...

  9. spring-data-redis 关于订阅客户端不断创建新线程的问题

    项目中使用了spring-data-redis 实现消息订阅功能,原来的配置是这样子: <redis:listener-container connection-factory="je ...

  10. selenium--页面元素是否可见和可操作

    判断元素是否可见 from selenium import webdriver import unittest class Test_Display(unittest.TestCase): def t ...