zoukankan      html  css  js  c++  java
  • Apache HttpClient使用之阻塞陷阱

     

    前言:
      之前做个一个数据同步的定时程序. 其内部集成了某电商的SDK(简单的Apache Httpclient4.x封装)+Spring Quartz来实现. 原本以为简单轻松, 喝杯咖啡就高枕无忧的事. 没想到该程序并不买账, work时间一久, 竟频频罢工还卖萌. 我勒个过去, 套用一句流行的话说: 真是青春日了狗了.

    相关文章的链接:
      第三方SDK(Rest API)和Jaskson的巧用 
      quartz和定时任务执行 

    现象回顾:
      最近发现数据同步迟滞了, 于是立马去check下服务进程. 发现进程活得好好的(白白胖胖那种), 稍松了口气, 看来没有OOM, 以及被误杀. 但日志没有滚动, 也就是说日志好久没更新了. 这是啥回事呢?
      难道说worker线程退出江湖了, 死锁大爷又来踢馆了, 还是说路遇张麻子(此山是我开, 此树是我栽)?
      使用jstack -l <pid>, 连续多次采样thread dump. 发现worker线程一直在read socket上等待.
      
      大概率上来讲, 进程是被堵塞了于此了.
      当然于此同时, 还发现了被动关闭, 哎呀妈呀, 问题还真不少.  
      

    问题分析:
      简单解读下某电商平台的SDK代码片段:

    public HttpResponse get(String method, HashMap<String,String> parames) throws Exception{
        String url = apiEntry + getParamStr(method, parames);
    
        HttpClient client = new DefaultHttpClient();
        HttpGet request = new HttpGet(url);
        request.addHeader("User-Agent", DefaultUserAgent);
        HttpResponse response = client.execute(request);
    
        return response;
    }

      代码很简洁, 也能很好地work, 那究竟哪个环节有疏忽呢?
      由于问题都出现在Apache Httpclient 4.x上, 因此我们先看看网上是否也有类似的案例场景.
      • socket阻塞
      参考了相关文章, 基本认可博文<<Apache HttpClient 没有设置time out导致应用长时间阻塞的问题>>中的说法: socket没有设置超时选项导致.
      具体解读, 可以理解为服务端对端不回应, 或者因网络异常, 导致socket一直阻塞于读. Apache HttpClient默认设置的socket为SO_TIMEOUT为0, 既无限等待.
      结合之上的代码分析, 确实忽视了超时设定, 陷入了Apache HttpClient隐藏很深的坑中. ^_^!
      解决方案是:为对应的httpclient设置超时即可.

    httpClient = new DefaultHttpClient(); 
    httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 2000); 
    httpClient.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 2000); 

      这样阻塞的问题就可以暂时告一段落了.
      • 句柄泄露(CLOSE_WAIT半连接关闭)
      同样参考了博文: <<HttpClient容易忽视的细节——连接关闭>>与<<HttpClient 与 Close_Wait>>.
      按apache httpclient的设计理念, 当http client 处于高并发时, 默认机制导致的CLOSE_WAIT会影响服务的可用性.
      对比之上的代码, 确实没有找到主动关闭连接的代码.
      Apache HttpClient本身变动多, 接口又杂, 以至每个版本的解决方案又有所不同, 有些让人眼花缭乱.
      比较一致的解决方式是,在处理完单个请求后, 调用如下清理代码:

    httpmethod.releaseConnection();
    client.getConnectionManager().shutdown();

      但不管怎么说, Apache HttpClient 4.x的关闭机制, 还是值得大书特书的, 这边显得简略, 希望以后有机会能深入研究.

    总结:
      这次算是事出有因, 问题出在了第三方的SDK上. 由此可见, 对第三方的SDK的使用, 还是得留个心眼. 实际上, 很多平台的SDK, 往往是实习生所编写的, 且没有经过严苛的测试, 所以质量难免有些参差不齐.
      无论是SDK的使用者, 还是SDK的开发者, 都需要精益求精, 在质量(性能和稳定), 用户体验(易用/易理解)上做足功夫了, 这也是程序员的软实力之一.

    后记:
      本文对Apache HttpClient 4.x的阻塞陷阱做了介绍, 展现了其案例表现, 以及解决方案. 但缺少对Apache HttpClient深入分析, 以及使用方式推荐. 希望自己能有机会, 好好地整理一番.

     公众号&游戏站点:
      个人微信公众号: 木目的H5游戏世界
      

      个人游戏作品集站点(尚在建设中...): www.mmxfgame.com,  也可直接ip访问http://120.26.221.54/.

  • 相关阅读:
    Serverless Wordpress 系列建站教程(五)
    剑指 Offer 13. 机器人的运动范围
    剑指 Offer 12. 矩阵中的路径
    网络相关知识
    网络相关知识(TCP部分)
    笔试中的流程控制题
    笔试:一些怕忘掉的基础东西
    笔试:处理输入基础
    设计模式:行为型->观察者模式
    设计模式:结构型->代理模式
  • 原文地址:https://www.cnblogs.com/mumuxinfei/p/5066633.html
Copyright © 2011-2022 走看看