当前位置: 首页 > news >正文

httpclient 优化

 (1)采用单例模式(重用HttpClient实例)
    对于一个通信单元甚至是整个应用程序,Apache强烈推荐只使用一个HttpClient的实例。例如:

    private static HttpClient httpClient = null;
 
    private static synchronized HttpClient getHttpClient() {
       if(httpClient == null) {
           final HttpParams httpParams = new BasicHttpParams();  
           httpClient = new DefaultHttpClient(httpParams); 
       }  
  
      return httpClient;
    }

    (2)保持连接(重用连接)
    对于已经和服务端建立了连接的应用来说,再次调用HttpClient进行网络数据传输时,就不必重新建立新连接了,而可以重用已经建立的连接。这样无疑可以减少开销,提升速度。
    在这个方面,Apache已经做了“连接管理”,默认情况下,就会尽可能的重用已有连接,因此,不需要客户端程序员做任何配置。只是需要注意,Apache的连接管理并不会主动释放建立的连接,需要程序员在不用的时候手动关闭连接。

    (3)多线程安全管理的配置
    如果应用程序采用了多线程进行网络访问,则应该使用Apache封装好的线程安全管理类ThreadSafeClientConnManager来进行管理,这样能够更有效且更安全的管理多线程和连接池中的连接。
    (在网上也看到有人用MultiThreadedHttpConnectionManager进行线程安全管理的,后查了下Apache的API,发现MultiThreadedHttpConnectionManager是API 2.0中的类,而ThreadSafeClientConnManager是API 4.0中的类,比前者更新,所以选择使用ThreadSafeClientConnManager。另外,还看到有PoolingClientConnectionManager这个类,是API 4.2中的类,比ThreadSafeClientConnManager更新,但Android SDK中找不到该类。所以目前还是选择了ThreadSafeClientConnManager进行管理)
    例如:

    ClientConnectionManager manager = new ThreadSafeClientConnManager(httpParams, schemeRegistry); 
    httpClient = new DefaultHttpClient(manager, httpParams);

    (4)大量传输数据时,使用“请求流/响应流”的方式
    当需要传输大量数据时,不应使用字符串(strings)或者字节数组(byte arrays),因为它们会将数据缓存至内存。当数据过多,尤其在多线程情况下,很容易造成内存溢出(out of memory,OOM)。
    而HttpClient能够有效处理“实体流(stream)”。这些“流”不会缓存至内存、而会直接进行数据传输。采用“请求流/响应流”的方式进行传输,可以减少内存占用,降低内存溢出的风险。
    例如:

    // Get method: getResponseBodyAsStream()
    // not use getResponseBody(), or getResponseBodyAsString()
    GetMethod httpGet = new GetMethod(url);  
    InputStream inputStream = httpGet.getResponseBodyAsStream();

    // Post method: getResponseBodyAsStream()
    PostMethod httpPost = new PostMethod(url);  
    InputStream inputStream = httpPost.getResponseBodyAsStream(); 

    (5)持续握手(Expect-continue handshake)
    在认证系统或其他可能遭到服务器拒绝应答的情况下(如:登陆失败),如果发送整个请求体,则会大大降低效率。此时,可以先发送部分请求(如:只发送请求头)进行试探,如果服务器愿意接收,则继续发送请求体。此项优化主要进行以下配置:

    // use expect-continue handshake
    HttpProtocolParams.setUseExpectContinue(httpParams, true);

    (6)“旧连接”检查(Stale connection check)
    HttpClient为了提升性能,默认采用了“重用连接”机制,即在有传输数据需求时,会首先检查连接池中是否有可供重用的连接,如果有,则会重用连接。同时,为了确保该“被重用”的连接确实有效,会在重用之前对其进行有效性检查。这个检查大概会花费15-30毫秒。关闭该检查举措,会稍微提升传输速度,但也可能出现“旧连接”过久而被服务器端关闭、从而出现I/O异常。
    关闭旧连接检查的配置为:
    // disable stale check
    HttpConnectionParams.setStaleCheckingEnabled(httpParams, false);

    (7)超时设置
    进行超时设置,让连接在超过时间后自动失效,释放占用资源。
    // timeout: get connections from connection pool
    ConnManagerParams.setTimeout(httpParams, 1000);  
    // timeout: connect to the server
    HttpConnectionParams.setConnectionTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);
    // timeout: transfer data from server
    HttpConnectionParams.setSoTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);

在Apache的HttpClient包中,有三个设置超时的地方:

/ 从连接池中取连接的超时时间/

ConnManagerParams.setTimeout(params, 1000);

/连接超时/

HttpConnectionParams.setConnectionTimeout(params, 2000);

/请求超时/

HttpConnectionParams.setSoTimeout(params, 4000);

第一行设置ConnectionPoolTimeout:

这定义了从ConnectionManager管理的连接池中取出连接的超时时间,此处设置为1秒。

第二行设置ConnectionTimeout:

这定义了通过网络与服务器建立连接的超时时间。Httpclient包中通过一个异步线程去创建与服务器的socket连接,这就是该socket连接的超时时间,此处设置为2秒。

第三行设置SocketTimeout:

这定义了Socket读数据的超时时间,即从服务器获取响应数据需要等待的时间,此处设置为4秒。

connectionTimeout:指的是连接一个url的连接等待时间。

soTimeout:指的是连接上一个url,获取response的返回等待时间


    (8)连接数限制
    配置每台主机最多连接数和连接池中的最多连接总数,对连接数量进行限制。其中,DEFAULT_HOST_CONNECTIONS和DEFAULT_MAX_CONNECTIONS是由客户端程序员根据需要而设置的。
    // set max connections per host
    ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(DEFAULT_HOST_CONNECTIONS)); 
    // set max total connections
    ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS);





   
  1. private static synchronized HttpClient getHttpClient() {
  2. if(httpClient == null) {
  3. final HttpParams httpParams = new BasicHttpParams();
  4. // timeout: get connections from connection pool
  5. ConnManagerParams.setTimeout(httpParams, 1000);
  6. // timeout: connect to the server
  7. HttpConnectionParams.setConnectionTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);
  8. // timeout: transfer data from server
  9. HttpConnectionParams.setSoTimeout(httpParams, DEFAULT_SOCKET_TIMEOUT);
  10. // set max connections per host
  11. ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(DEFAULT_HOST_CONNECTIONS));
  12. // set max total connections
  13. ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS);
  14. // use expect-continue handshake
  15. HttpProtocolParams.setUseExpectContinue(httpParams, true);
  16. // disable stale check
  17. HttpConnectionParams.setStaleCheckingEnabled(httpParams, false);
  18. HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);
  19. HttpProtocolParams.setContentCharset(httpParams, HTTP.UTF_8);
  20. HttpClientParams.setRedirecting(httpParams, false);
  21. // set user agent
  22. String userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2) Gecko/20100115 Firefox/3.6";
  23. HttpProtocolParams.setUserAgent(httpParams, userAgent);
  24. // disable Nagle algorithm
  25. HttpConnectionParams.setTcpNoDelay(httpParams, true);
  26. HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE);
  27. // scheme: http and https
  28. SchemeRegistry schemeRegistry = new SchemeRegistry();
  29. schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
  30. schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
  31. ClientConnectionManager manager = new ThreadSafeClientConnManager(httpParams, schemeRegistry);
  32. httpClient = new DefaultHttpClient(manager, httpParams);
  33. }
  34. return httpClient;
  35. }



相关文章:

  • PHPCMSV9上线方法及文件权限设置
  • 推理题:猜扑克牌
  • JS获取首字母
  • zabbix-----5-----自动发现的概念
  • NTP时钟同步学习记录
  • java基础知识 构造方法
  • 在 Chrome DevTools 中调试 JavaScript 入门
  • IntelliJ IDEA 主题、字体、编辑区主题、文件编码修改
  • mediawiki登录时第一次会跳回登录页面,第二次才能登录成功
  • 更换好的yum源
  • 初识cesium----加载不同JSON格式例子
  • 《React Native高效开发》之create-react-native-app
  • 算法(Algorithms)第4版 练习 2.3.25
  • Matlab中imnoise函数的用法
  • docker 配置缓存代理服务apt-cacher-ng
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • Android组件 - 收藏集 - 掘金
  • CEF与代理
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • js如何打印object对象
  • js算法-归并排序(merge_sort)
  • laravel5.5 视图共享数据
  • Linux gpio口使用方法
  • 程序员该如何有效的找工作?
  • 订阅Forge Viewer所有的事件
  • 京东美团研发面经
  • 前端之React实战:创建跨平台的项目架构
  • 浅谈Golang中select的用法
  • 巧用 TypeScript (一)
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • 阿里云重庆大学大数据训练营落地分享
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • # include “ “ 和 # include < >两者的区别
  • #LLM入门|Prompt#2.3_对查询任务进行分类|意图分析_Classification
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (2022 CVPR) Unbiased Teacher v2
  • (C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (附源码)计算机毕业设计高校学生选课系统
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (篇九)MySQL常用内置函数
  • (转)【Hibernate总结系列】使用举例
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转)ORM
  • .NET MVC之AOP
  • .NET 的程序集加载上下文
  • .net 微服务 服务保护 自动重试 Polly
  • .net和php怎么连接,php和apache之间如何连接
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比