首页 > 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. GitHub Pages 与 Gitee Pages 上的 Jekyll

    GitHub 与 Gitee 提供的 Pages 服务中,均内嵌了 Jekyll 支持(Gitee 还提供了 Hugo 与 Hexo 支持).所谓「支持」,即指这些生成工具挂在云端:你只需要提供原始代 ...

  2. sqlserver 分页模糊查询

       积少成多 ----  仅以此致敬和我一样在慢慢前进的人儿 问题: 在sqlserver 进行模糊查询,出现问题 最初使用“concat”,进行拼串操作,如下所示: <select id = ...

  3. Informatica9.5.1配置域名错误(ICMD_10033,INFASETUP_10002,RSVCSHARED_00021)

    错误信息: OutPut : [ICMD_10033] Command [defineDomain] failed with error [[INFASETUP_10002] Cannot creat ...

  4. C# list中ConvertAll的使用

    static double TakeSquareRoot(int x) { //return Math.Sqrt(x); ; } static void Main(string[] args) { L ...

  5. freemark 基本使用

    实际上用程序语言编写的程序就是模板. FTL (代表FreeMarker模板语言). 这是为编写模板设计的非常简单的编程语言. 模板(FTL编程)是由如下部分混合而成的: 文本:文本会照着原样来输出. ...

  6. iOS 利用UICollectionView做一个无限循环广告栏

    一.效果图 左右丝滑滑动,并且有缩放动画. 二.分析和思路 1. 为什么选择用UICollectionView去做上面的效果? 首先无限效果永远是表现出来的,而不是程序里面创建了无数个view,如何做 ...

  7. ReLU函数

    Rectifier(neural networks) 在人工神经网络中,rectfier(整流器,校正器)是一个激活函数,它的定义是:参数中为正的部分. , 其中,x是神经元的输入.这也被称为ramp ...

  8. eclipse新下载,安装和配置

    question1 java11没有jre,无法通过eclipse-inst-win64进行安装 solution Windows 7 64bit 安装jdk i586还是jdk x64?jdk x6 ...

  9. Go语言实现:【剑指offer】机器人的运动范围

    该题目来源于牛客网<剑指offer>专题. 地上有一个m行和n列的方格.一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之 ...

  10. 一个"/"引发的惨案

    今天行云流水写了一个接口,正想着写完就睡觉了,结果访问的时候一直报错404,找不到路径,我反复检查了好久,确定路径名字没写错,百思不得其解,瞬间有想砸电脑的冲动,于是准备洗洗睡了,明天再搞 洗玩脚回到 ...