记一次工作中的重大BUG---http连接池

很晚了,但是还是决定打开电脑记录下最近一段时间遇到的问题。
事情是这样的,前段时间公司一个同事ZM休婚假,我就接手了他手上的一家比较重要的保险公司(暂时成为RB吧,我们是一家保险销售平台,上海最会保),其实一开始我是拒绝的,因为这家公司实际上的流程不是正常的,因为它是爬取的,而且据说有很多坑(事后发现并不是那样夸张吧)。

说爬取,其实也就是用httpClient模拟浏览器的行为,然后用htmlParse解析xml,然后在模拟提交表单之类。我在程序入口处将要访问的链接log一下,用浏览器去访问这个链接直接能够打开,但是httpClient却经常抛socketTimeoutException,这就奇怪了,难道是cookie有问题?RB服务器没有检测到所需要的cookie?然后这个http connect就一直被idle了?但是我是访问RB的第一个链接啊,明显不需要任何cookie啊,第一个猜想被pass掉;好吧,继续猜想!难道是没有完全模拟浏览器?为此做了如下httpHeader设置:

private void setHttpHeader(HttpMethod method, String referSuffix, boolean isAjax){   
    method.setRequestHeader("Accept", "text/html, */*; q=0.01");    
    method.setRequestHeader("Accept-Encoding", "gzip, deflate");
    method.setRequestHeader("Accept-Language","zh-CN,zh;q=0.8,en;q=0.6");
    method.setRequestHeader("Cache-Control", "no-cache");
    method.setRequestHeader("Connection", "Keep-Alive");
    method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;");
    method.setRequestHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36");
    method.setRequestHeader("Host", "www.epicc.com.cn");
    method.setRequestHeader("Referer", BASE_URL + referSuffix);
    method.setRequestHeader("Origin","http://www.epicc.com.cn");
    if (isAjax){
        method.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    }
}

每次构造get或者post的时候调用此方法来设置头,然而并没有啥用处,依然socketTimeoutException;
然后我就蒙圈了,各种想,然而并没有什么头绪!其实我当时想的是我应该用log4j打印一下httpClient的debug的log的,或许能够找到原因;
另一个同事WL先tcpdump抓了包,ZM和WL工作8年的老程序员,果然还是经验很重要,然后就分析出来了,分析发现正常情况下,http发送前都需要进行tcp握手建立连接,然后再http发送报文,然而使用了连接池后,每次http请求结束后,这些连接会被放回连接池,直到下次被使用,但是我们不知道的是,可能这个时候服务器已经把这个连接断开了,而第二次如果有请求发现连接池中有连接空闲,就未经检查就使用了这个connection,这样无法发送报文,就好抛出socketTimeoutException,这就是为什么有时候会socketTimeout,有时候不会,因为这个connection不知道有没有被服务器shutdown掉,如果关闭了,则异常呗!

如何使用?

MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
HttpConnectionManagerParams params = connectionManager.getParams();
params.setConnectionTimeout(30000);
params.setSoTimeout(60000);
params.setDefaultMaxConnectionsPerHost(1000);
params.setMaxTotalConnections(1000);
httpClient = new HttpClient(connectionManager);

当初使用MultiThreadedHttpConnectionManage(关于)是为了复用连接的连接,解决办法就是不用连接池了呗,每个service实例中都存有一个共享的httpClient,这样多次发起http请求也可以公用这个httpClient;

当然最好的解决办法或者说是使用MultiThreadedHttpConnectionManage的错误是由于没有设置正确的参数,HttpConnectionParams中有一个方法:

/**
   * Defines whether stale connection check is to be used. Disabling
   * stale connection check may result in slight performance improvement
   * at the risk of getting an I/O error when executing a request over a
   * connection that has been closed at the server side.
   * @param value <tt>true</tt> if stale connection check is to be used,
   * <tt>false</tt> otherwise.
   */
   public void setStaleCheckingEnabled(boolean value) {
      setBooleanParameter(STALE_CONNECTION_CHECK, value);
   }

设置true后每次使用连接池中的链接会先检查下链接是否可用;虽然可能会消耗15-30ms,但是这个应该比tcp握手来的快。

其实任然还有很多优化的地方,如失败重试等等;

另外整理了一下HTTP Client MultiThreadedHttpConnectionManager线程安全连接管理类源码解析
请看:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • http协议有http0.9,http1.0,http1.1和http2三个版本,但是现在浏览器使用的是htt...
    一现_阅读 1,855评论 0 3
  • HTTP cookie(也称为web cookie,网络cookie,浏览器cookie或者简称cookie)是网...
    留七七阅读 17,811评论 2 71
  • 赤身浴清风, 扬手敛秋意。 独观暮色晚, 静候明月还。 自恃一毫墨, 亦敢赋桂香。 只待仲秋月, 斗胆撰文章。
    微光奇迹阅读 290评论 0 5
  • 中国有句古话,叫做慈不带兵、义不行贾。当领导的人,如果没有一份“铁石心肠”,以及强硬的手腕,是难以带领下级和单位的...
    Jonpch阅读 2,144评论 0 0