首页 > JAVA > @Scheduled和HttpClient的连环坑

@Scheduled和HttpClient的连环坑

2018-03-22

曾经踩过一个大坑:

由于业务特殊性,会定时跑很多定时任务,对业务数据进行补偿操作等。

在Spring使用过程中,我们可以使用@Scheduled注解可以方便的实现定时任务。

有一天早上突然发现,从前一天晚上某一时刻开始,所有的定时任务全部都卡死不再运行了。

@Scheduled默认单线程

经排查后发现,我们使用@Scheduled注解默认的配置的话,所有的任务都是单线程去跑的。写了一个测试的task让它sleep住,就很容易发现,其他所有的task在时间到的时候都没有触发。

如果需要开启多线程处理,则需要进行如下的配置,设置一下线程数:

@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));
}
}

这样就解决了如果一个task卡住,会引起所有task全部卡住的问题。

但是为什么会有task卡住呢?

HttpClient默认参数配置

原来,有些task会定时请求外部服务的restful接口,而httpClient的配置如下:

PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(maxConnection);
httpClient = HttpClients.custom()
.setConnectionManager(connManager)
.build();

在最开始使用HttpClient的时候,根本没有想这么多,基本也都是用用默认配置。

追踪源码可以发现,在使用上述方式进行配置的时候,httpClient的timeout时间竟然全部都是-1,也就是说如果对方服务有问题,httpClient的请求会永不超时,一直等待。源码如下:

Builder() {
super();
this.staleConnectionCheckEnabled = false;
this.redirectsEnabled = true;
this.maxRedirects = 50;
this.relativeRedirectsAllowed = true;
this.authenticationEnabled = true;
this.connectionRequestTimeout = -1;
this.connectTimeout = -1;
this.socketTimeout = -1;
this.contentCompressionEnabled = true;
}

所以我们这时候必须手动指定timeout时间,问题就解决了。例如:

PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(maxConnection);
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setSocketTimeout(3000)
.setConnectTimeout(3000)
.setConnectionRequestTimeout(3000)
.build();
httpClient = HttpClients.custom()
.setDefaultRequestConfig(defaultRequestConfig)
.setConnectionManager(connManager)
.build();

联想到另一个问题

其实HttpClient的使用过程中也遇到过另外一个配置的问题,就是defaultMaxPerRoute这个参数。

最开始使用的时候也没有注意过这个参数,只是设置过连接池的最大连接数maxTotal。

defaultMaxPerRoute参数其实代表了每个路由的最大连接数。比如你的系统需要访问另外两个服务:google.com 和 bing.com。如果你的maxTotal设置了100,而defaultMaxPerRoute设置了50,那么你的每一个服务的最大请求数最大只能是50。

那么如果defaultMaxPerRoute没有设置呢,追踪源码:

public PoolingHttpClientConnectionManager(
final HttpClientConnectionOperator httpClientConnectionOperator,
final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory,
final long timeToLive, final TimeUnit tunit) {
super();
this.configData = new ConfigData();
//这里使用的CPool构造方法,第二个参数即为defaultMaxPerRoute,也就是默认为2。
this.pool = new CPool(new InternalConnectionFactory(
this.configData, connFactory), 2, 20, timeToLive, tunit);
this.pool.setValidateAfterInactivity(2000);
this.connectionOperator = Args.notNull(httpClientConnectionOperator, "HttpClientConnectionOperator");
this.isShutDown = new AtomicBoolean(false);
}

这里发现,原来默认值竟然只有2。怪不得当时在高并发情况下总会出现超时,明明maxTotal已经设的很高。

所以如果你的服务访问很多不同的外部服务,并且并发量比较大,一定要好好配置maxTotal和defaultMaxPerRoute两个参数。

所以后来再使用任何新的东西,都有好好看下都什么配置,有疑问的一定要先查一下,不要网上copy一段代码直接就用。当时可能没问题,但是以后没准就被坑了。

原文链接:https://segmentfault.com/a/1190000013914327

Scheduled和HttpClient的连环坑的更多相关文章

  1. HttpClient的巨坑

    之前做项目的时候,调用api都是使用的HttpWebRequest 最近一个项目改用HttpClient,用了之后,感觉很坑. 1.高并发情况下,造成tcp连接占用的端口无法释放(时间为2MSL,此时 ...

  2. 关于为了一时方便,使用@Scheduled注解定时踩的坑

    摘要: 事情是这样的前两周在做项目的时候碰到一个需求---要求每天晚上执行一个任务,公司统一使用的是 xxl-job 写定时任务的,我当时为了方便自己,然后就简单的使用了Spring的那个@Sched ...

  3. HttpClient在多线程环境下踩坑总结

    问题现场 在多线程环境下使用HttpClient组件对某个HTTP服务发起请求,运行一段时间之后发现客户端主机CPU利用率呈现出下降趋势,而不是一个稳定的状态. 而且,从程序日志中判断有线程处于han ...

  4. 到处都是坑的微信支付V3

    业务需要一个在微信上能付款的功能,于是乎想到了最普遍的支付宝,坑爹的是T与A是水火不容啊,默默的还是接微信支付吧,没想到从此掉进了连环坑…… 网上写微信支付接口的还是很多,PHP官方有(鄙视源码作者, ...

  5. 分布式监控系统Zabbix3.2跳坑指南

    zabbix是什么在此就不多作介绍了,可以参考之前的文章 零代码如何打造自己的实时监控预警系统 ,这篇主要介绍安装及注意事项. 主要分为服务端和客户端安装,客户端又分为Linux.Windows. 服 ...

  6. Rust入坑指南:智能指针

    在了解了Rust中的所有权.所有权借用.生命周期这些概念后,相信各位坑友对Rust已经有了比较深刻的认识了,今天又是一个连环坑,我们一起来把智能指针刨出来,一探究竟. 智能指针是Rust中一种特殊的数 ...

  7. 线上问题排查,一不小心踩到阿里的 arthas坑了

    最近帮新来的校招同学排查一个线上问题,问题本身不是很难,但是过程中踩到了一个arthas的坑,挺有意思的. 同时,也分享下在排查过程中使用的一些比较实用的工具,包括tcpdump.arthas.sim ...

  8. (WebFlux)004、WebFilter踩坑记录

    一.背景 使用SpringWebFlux的WebFilter时,由于不熟悉或一些思考疏忽,容易出现未知的异常.记录一下排查与解决方案,给大家分享一下. 二.问题 2.1 问题描述 在测试接口方法时,出 ...

  9. php+mysql+apache项目运行所遇到的一系列配置问题

    今天运行一个php项目时,突然发现访问不了了.起因应该是mac系统升级,导致apache配置文件完全恢复到了默认状态,一切归零.作为一个经验尚欠的前端,对这些后台配置完全是一窍不通,赶紧微信联系了小胖 ...

随机推荐

  1. 2020年薪30W的Java程序员都要求熟悉JVM与性能调优!

    前言 作为Java程序员,你有没有被JVM伤害过?面试的时候是否碰到过对JVM的灵魂拷问?   一.JVM 内存区域划分 1.程序计数器(线程私有) 程序计数器(Program Counter Reg ...

  2. X-CTF(REVERSE高级) Reversing-x64Elf-100

    逻辑很简单,如果sub_4006FD函数返回假则返回Nice! 图1 进入sub_4006FD函数,加密过程也很简单,这里值得注意的有两点 一.8*(i%3)是二维数组的第一个参数,这里是取v3的地址 ...

  3. 【译】SQ3R学习法则

    SQ3R 观察-提问-阅读-复述-回顾 背景 SQ3R是一种理解策略,可帮助学生在阅读时思考他们正在阅读的文章. SQ3R通常被归类为学习策略,通过教导学生在初次阅读一篇文章时如何阅读和像高效读者一样 ...

  4. DirectX11 With Windows SDK--30 图像模糊、索贝尔算子

    前言 到这里计算着色器的主线学习基本结束,剩下的就是再补充两个有关图像处理方面的应用.这里面包含了龙书11的图像模糊,以及龙书12额外提到的Sobel算子进行边缘检测.主要内容源自于龙书12,项目源码 ...

  5. The current test process

    样机测试 测试前: 工作内容: 1.需求分析.编写.评审: 项目开工会由项目负责人参加,参加会议时做好笔记,对项目的功能类似,功能模块,测试时间点有个大致的了解. 原始需求进行需求文档细化:按照模块进 ...

  6. 高软期末考试 B2C模式

    一.软件工程知识点 简要总结 1.软件基础知识 瀑布模型: 我感觉整个<软件工程>书的布局就是按照瀑布模型来的,上面右图少个运维. 2.UML图 2.1 用例图 UseCase Diagr ...

  7. 一个新实验:使用gRPC-Web从浏览器调用.NET gRPC服务

    今天给大家翻译一篇由ASP.NET首席开发工程师James Newton-King前几天发表的一篇博客,文中带来了一个实验性的产品gRPC-Web.大家可以点击文末的讨论帖进行相关反馈.我会在文章末尾 ...

  8. partition show for oracle version

    Dear all You may remember that my blog has a view script for checking sqlserver partition tables. No ...

  9. 用MYSQL的存储过程创建百万级测试数据表

    创建随机字符串函数,便于创建名称 DROP function if EXISTS rand_string; #创建一个指定字符个数的函数 create function rand_string(n I ...

  10. Ansible: hosts文件拆分为inventory和定义inventory全局变量

    前言 随着管理机器的增多,我们在使用Ansible的时候时常会遇到hosts文件过于冗长的问题,极其不便于管理,而将hosts文件拆分为inventory就可解决该问题:另外,hosts中的每个主机条 ...