Spring Cloud config之三:config-server因为server端和client端的健康检查导致服务超时阻塞问题
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端的健康检查导致服务超时阻塞问题的更多相关文章
- Spring Cloud 入门 之 Config 篇(六)
原文地址:Spring Cloud 入门 之 Config 篇(六) 博客地址:http://www.extlight.com 一.前言 随着业务的扩展,为了方便开发和维护项目,我们通常会将大项目拆分 ...
- Spring Cloud 系列之 Config 配置中心(三)
本篇文章为系列文章,未读前几集的同学请猛戳这里: Spring Cloud 系列之 Config 配置中心(一) Spring Cloud 系列之 Config 配置中心(二) 本篇文章讲解 Conf ...
- Spring Cloud Alibaba Nacos Config 实战
Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持.使用 Spring Cloud Alibaba Nacos Config,您可 ...
- Spring Cloud 系列之 Config 配置中心(二)
本篇文章为系列文章,未读第一集的同学请猛戳这里:Spring Cloud 系列之 Config 配置中心(一) 本篇文章讲解 Config 如何实现配置中心自动刷新. 配置中心自动刷新 点击链接观看: ...
- Spring Cloud Alibaba Nacos Config 的使用
Spring Cloud Alibaba Nacos Config 的使用 一.需求 二.实现功能 1.加载 product-provider-dev.yaml 配置文件 2.实现配置的自动刷新 3. ...
- 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 ...
- 在socket的server端处理client端发来的数据
一.楔子 最近做了一个需求遇到一个坑,归结成一个小问题,其实就是在socket的server端处理client端发来的数据的问题,现将这个问题总结一下,本文将数据在server端以字典的形式存储. 另 ...
- 用同一台PC的两个网口实现Iperf的server端和client端
用同一台PC的两个网口实现Iperf的server端和client端 2015年10月20日 20:35:11 阅读数:2943 有时候需要发包,仅仅需要一定速率的流量,并不需要关心收到报文的大小,一 ...
- spring cloud 学习(5) - config server
分布式环境下的统一配置框架,已经有不少了,比如百度的disconf,阿里的diamand.今天来看下spring cloud对应的解决方案: 如上图,从架构上就可以看出与disconf之类的有很大不同 ...
随机推荐
- 使用IDEA重构代码
使用IDEA提供的快捷操作,高效快速重构代码. 常用重构快捷菜单 Shift+F6,重构 - 重命名 Ctrl+Alt+m,提取方法 F6,移动方法
- CTF-代码审计(2)
1.bugku 备份是个好习惯 网址:http://123.206.87.240:8002/web16/ 进去什么都没有,题目说备份想到备份文件,所以直接再后面加个 .bak 拿到源码: < ...
- fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC
出现如下错误: fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires ...
- ASP.NET----内置对象----Resuest
Request对象可以获取包含用户的计算机.页面及浏览器的请求等相关信息. Request对象的属性: ①Form----------返回有关表单变量的集合 ②QueryString--------- ...
- OpenSSL生成私钥和公钥
1.生成私钥 -- 生成 RSA 私钥(传统格式的) openssl genrsa -out rsa_private_key.pem 1024 -- 将传统格式的私钥转换成 PKCS#8 格式的(JA ...
- Linux的IP详解
俗话说:黑发不知勤学早,白首方悔读书迟. ...
- Unity 渲染教程(一):矩阵
转载:http://gad.qq.com/program/translateview/7181958 创建立方体网格.· 支持缩放.位移和旋转. · 使用变换矩阵. · 创建简单的相机投影. 这是关于 ...
- seq2seq模型详解及对比(CNN,RNN,Transformer)
一,概述 在自然语言生成的任务中,大部分是基于seq2seq模型实现的(除此之外,还有语言模型,GAN等也能做文本生成),例如生成式对话,机器翻译,文本摘要等等,seq2seq模型是由encoder, ...
- 15-C#笔记-结构体
示例: using System; using System.Text; struct Books { private string title; // 支持 public private strin ...
- USACO Superprime Rib
洛谷 P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib 洛谷传送门 JDOJ 1673: Superprime Rib JDOJ传送门 题目描述 农民约翰的母牛总是产生最好 ...