HttpClient有关方法及相关优化整理

HttpClient4中采用
ThreadSafeClientConnManager来保证线程的安全,优于2.0的
MultiThreadedHttpConnectionManager类。另外Apache官方强烈推荐只使用一个HttpClient的实例,所以我
们可以将以下demo方法写成单例模式。
demo将使用StringEntity来完成不指定参数名发送Post,已经采用ThreadSafeClientConnManager来保证线程的安全

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

public String sendToHttpClientGprs(String url,String content) {

BufferedReader reader = null;

StringBuffer stringBuffer = null;

HttpParams httpParams = new
BasicHttpParams();

// 设置超时

ConnManagerParams.setTimeout(httpParams, 5*1000);

HttpConnectionParams.setConnectionTimeout(httpParams, 5*1000);

HttpConnectionParams.setSoTimeout(httpParams, 5*1000);

// 多线程最大连接数

ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new
ConnPerRouteBean(5));

// 多线程总连接数

ConnManagerParams.setMaxTotalConnections(httpParams, 10);

// 设置异常处理机制

HttpProtocolParams.setUseExpectContinue(httpParams, true);

// 设置是否检查旧连接

HttpConnectionParams.setStaleCheckingEnabled(httpParams, false);

// 设置版本

HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);

// 设置编码

HttpProtocolParams.setContentCharset(httpParams, HTTP.UTF_8);

// 设置重定向

HttpClientParams.setRedirecting(httpParams, false);

// 设置userAgent

String userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2) Gecko/20100115 Firefox/3.6";

HttpProtocolParams.setUserAgent(httpParams, userAgent);

//设置是否延迟发送

HttpConnectionParams.setTcpNoDelay(httpParams, true);

//设置缓存大小

HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE);

// 支持http与https

SchemeRegistry schemeRegistry = new
SchemeRegistry();

schemeRegistry.register(new
Scheme("http", PlainSocketFactory.getSocketFactory(), 80));

schemeRegistry.register(new
Scheme("https", SSLSocketFactory.getSocketFactory(), 443));

//ThreadSafeClientConnManager线程安全管理类

ClientConnectionManager manager = new
ThreadSafeClientConnManager(httpParams, schemeRegistry);

HttpClient   client = new
DefaultHttpClient(manager, httpParams);

//post请求

HttpPost httppost =  new
HttpPost(path);

httppost.setHeader("connection", "Keep-Alive");

httppost.setHeader("Content-Type", "text/plain");

try {

//直接传入发送内容,不指定参数名

StringEntity myEntity = new
StringEntity(content, "UTF-8");

httppost.setEntity(myEntity);

// 发送请求

HttpResponse response = client.execute(httppost);

Log.i("ResponseCode", response.getStatusLine().getStatusCode() + "");

// 请求成功

if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

reader = new
BufferedReader(new
InputStreamReader(response.getEntity().getContent()));

stringBuffer = new
StringBuffer();

String line = "";

while
((line = reader.readLine()) != null) {

stringBuffer.append(line);

}

}

} catch
(Exception e) {

e.printStackTrace();

finally
{

try {

// 关闭流

if (null != reader) {

reader.close();

reader = null;

}

} catch
(IOException e) {

e.printStackTrace();

}

}

if (null == stringBuffer) {

return
"-1";

} else
{

return
stringBuffer.toString();

}

}

先看看以前的代码,每次请求都会创建一个HttpClient,代码如下:

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

HttpClient client = getHttpClient(5000, 5000);

GetMethod getMethod = new
GetMethod(url);

getMethod.setQueryString(parameter);

byte[] responseBody = null;

try {

    int
statusCode = client.executeMethod(getMethod);

    if
(statusCode != HttpStatus.SC_OK) {

        logger.error("error !"
+ url + ",statusCode "
+ statusCode);

    }

    responseBody = getMethod.getResponseBody();

}catch
(IOException e) {

    logger.error("error!"
+ url, e);

} finally
{

   getMethod.releaseConnection();

}

这是最简单的代码,很多例子就是这样开始的,如果少量请求还行,请求很频繁的话,这样的代码不是很好。(注意这里连接用完后必须释放连接)。

首先,HttpClient可以共用,减少创建HttpClient的开销。当然,如果你的应用调用HttpClient并不怎么频繁的话那就没必要共用了,毕竟在内存中维护一个空闲的httpClient对象是不保险的。

其次,Connection可以重用,减少建立连接的开销。

要完成以上两点,可以用多线程下的MultiThreadedHttpConnectionManager管理HttpConnection和
HttpClient。MultiThreadedHttpConnectionManager管理的HttpClient是线程安全的,可以做成单例
的。但是值得注意的是每个线程应该有自己的HttpMethod和HttpState、HttpConfiguration,以区分每次请求的host和
HttpSession 。如下所示:

private static MultiThreadedHttpConnectionManager httpConnectionManager = new MultiThreadedHttpConnectionManager();

private HttpClient client = new HttpClient(httpConnectionManager);


定义好后,在静态块中初始化相关参数

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

static {             

    //每主机最大连接数和总共最大连接数,通过hosfConfiguration设置host来区分每个主机 

    client.getHttpConnectionManager().getParams().setDefaultMaxConnectionsPerHost(8);

    client.getHttpConnectionManager().getParams().setMaxTotalConnections(48);

    client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);

    client.getHttpConnectionManager().getParams().setSoTimeout(5000);

    client.getHttpConnectionManager().getParams().setTcpNoDelay(true);

    client.getHttpConnectionManager().getParams().setLinger(1000);                  

    //失败的情况下会进行3次尝试,成功之后不会再尝试

    client.getHttpConnectionManager().getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new
DefaultHttpMethodRetryHandler());

}

HttpConfiguration中有一些参数对提高性能有一些帮助,主要说明如下:

DefaultMaxConnectionsPerHost参数定义每台主机允许的最大连接数,默认为2。这个参数只能用于一些特定的httpConnectionManager,比如MultiThreadedHttpConnectionManager。

MaxTotalConnections参数表示httpConnectionManager管理的最大连接数,默认为20。同上个参数,这个参数也只是在某些特定的httpConnectionManager中有用。
setTcpNoDelay(true)设置是否启用Nagle算法,设置true后禁用Nagle算法,默认为false(即默认启用Nagle算
法)。Nagle算法试图通过减少分片的数量来节省带宽。当应用程序希望降低网络延迟并提高性能时,它们可以关闭Nagle算法,这样数据将会更早地发
送,但是增加了网络消耗。

setLinger(1000)设置socket延迟关闭时间,值为0表示这个选项是关闭的,值为-1表示使用JRE的默认设置。
setStaleCheckingEnabled(true)参数设置是否启用旧连接检查,默认是开启的。关闭这个旧连接检查可以提高一点点性能,但是增
加了I/O错误的风险(当服务端关闭连接时)。开启这个选项则在每次使用老的连接之前都会检查连接是否可用,这个耗时大概在15-30ms之间[3]。

然后,在每个线程代码中,创建自己的HttpMethod。

还有一个很重要的优化点是采用请求/响应实体流,尤其是在请求频繁数据量大的情况下,很大的实体不会被缓存在内存中而直接发送或接收,采用流能有效的提高
性能。虽然这些实体可以是字符串或者字节数组,但是它们容易导致内存泄露,你得小心的使用他们,因为它们是整个实体缓存在内存中的。

对于响应流,采用method的getResponseBodyAsStream()来代替getResponseBody()
和getResponseBodyAsString().如下所示:

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

HttpClient httpclient = new
HttpClient();

  GetMethod httpget = new
GetMethod("http://www.myhost.com/");

  try
{

    httpclient.executeMethod(httpget);

    Reader reader = new
InputStreamReader(httpget.getResponseBodyAsStream(), httpget.getResponseCharSet());

    // consume the response entity

  } finally
{

    httpget.releaseConnection();

  }

而对于请求流,可以通过实现RequestEntity自定义自己的各种流,httpclient包含了常见的几种实现,如
FileRequestEntity、ByteArrayRequestEntity、StringRequestEntity、
MultipartRequestEntity等。使用示例如下:

?





1

2

3

4

5

File myfile = new
File("myfile.txt");

PostMethod httppost = new
PostMethod("/stuff");

httppost.setRequestEntity(new
FileRequestEntity(myfile));

如果客户端和服务器的通讯不需要保持会话状态的话,可以通过禁用Cookie来提高一点点性能,比如蜘蛛爬虫之类应用。如下:

?





1

2

3

4

5

HttpMethod method = new
GetMethod();

method.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);

method.setRequestHeader("Cookie", "special-cookie=value");

HttpClient有关方法及相关优化整理

时间: 2024-10-10 04:21:41

HttpClient有关方法及相关优化整理的相关文章

【webapp的优化整理】要做移动前端优化的朋友进来看看吧

单页or多页 本文仅代表个人观点,不足请见谅,欢迎赐教. webapp 小钗从事单页相关的开发一年有余,期间无比的推崇webapp的网站模式,也整理了很多移动开发的知识点,但是现在回过头来看,webapp究竟是好还是不好真是一言难尽哟! webapp使用JavaScript修改页面:紧接着再从服务器传递更多数据然后再修改页面,如此循环. 从性能的角度看,在现代浏览器中单页面Web App已经能够和普通native应用程序相媲美,而且几乎所有的操作系统都支持现代的浏览器. 所以,很多人认为weba

Redis相关知识整理

Redis相关知识整理 1. Redis和MySQL的区别?a).mysql是关系型数据库,而redis是NOSQL,非关系型数据库.mysql将数据持久化到硬盘,读取数据慢,而redis数据先存储在缓存中,读取速度快,但是保存时间有限,最后按需要可以选择持久化到硬盘. b).mysql作为持久化数据库,每次访问都要在硬盘上进行I/O操作.频繁访问数据库会在反复连接数据库上花费大量时间.redis则会在缓存区存储大量频繁访问的数据,当浏览器访问数据的时候,先访问缓存,如果访问不到再进入数据库.

C#:WebBrowser控件的使用教程及相关问题整理

推荐阅读: C#WebBrowser控件使用教程与技巧收集--苏飞收集 C# webBrowser强制在本窗口打开,禁止在新窗口打开 C# webBrowser禁止在新窗口打开,强制在本窗口打开(多种方法整理) 如何解决WebBrowser.DocumentCompleted事件的多次调用 Webbrowser控件判断网页加载完毕的简单方法 C#中的WebBrowser控件的使用 挺全的WebBrowser资料 待续-- C#:WebBrowser控件的使用教程及相关问题整理,布布扣,bubuk

【Oracle 优化】Oracle数据库提高命中率及相关优化

本文是关于Oracle数据库调试与优化方面的文章,主要介绍Oracle数据库中命中率相关的问题,包括不同的算法之间性能的比对. 关于Oracle中各个命中率的计算以及相关的调优 1)Library Cache的命中率: .计算公式:Library Cache Hit Ratio = sum(pinhits) / sum(pins) SQL>SELECT SUM(pinhits)/sum(pins) FROM V$LIBRARYCACHE; 通常在98%以上,否则,需要要考虑加大共享池,绑定变量,

根据网站所做的SEO优化整理的一份文档

今日给合作公司讲解本公司网站SEO优化整理的一份简单文档 架构 ########################################## 1.尽量避免Javascript和flash导航. 虽然JS和FLASH能把网站做的绚丽漂亮,但目前搜索引擎还是无法顺利的抓取其中的内容,所以我们要避免. 2.目录层次不能太深. 网站目录尽量保持在三层以内,尽可能接近根网址,比如“www.xxx.com/产品目录/产品名称”明显比“www.xxx.com/产品目录/年份/月份/产品名称”要好. 3

sqlserver2008 死锁解决方法及性能优化方法

sqlserver2008 死锁解决方法及性能优化方法 原文: http://blog.csdn.net/kuui_chiu/article/details/48621939 十步优化SQL Server中的数据访问 http://tech.it168.com/a2009/1125/814/000000814758_2.shtml 关于死锁: [sql] view plain copy sp_who active  --看看哪个引起的死锁, blk里面即阻塞的spid: dbcc inputbu

cxf 相关知识整理

① 请求方式为GET @GET @Path(value = "/userAddressManage") @Produces( { MediaType.APPLICATION_JSON, "text/html; charset=UTF-8" }) public BuyerAddressResponseModel userAddressManage( @QueryParam("buyerTel") String buyerTel, @QueryPar

位运算相关内容整理

位运算相关内容整理 1) 负数 负数的右移:负数右移的话,由于要保持它是负数,所以负数的二进制的左边补1.如果一直右移的话,最后就就变成0xFFFFFFFF 即-1 如: -4>>1 为-2 :-4>>2为-1 负数的左移:跟正整数左移一样,右边补0.左移总是在低位补零,高位丢失,因而负数左移后可能会变成正数. int x = 0x8fff0000; cout << (x << 1); // 输出为536739840 cout << (-2 &l

Apache的相关优化

Apache的相关优化 一.Apache运行环境优化 1.使用单独的主机运行Apache服务     Apache所运行的硬件环境都是对性能影响最大的因素,即使不能对硬件进行升级,也最好给apache一个单独的主机以免受到其他应用的干扰. 2.给Apache服务器增加内存 所有硬件指标中,对性能影响最大的是内存,对于静态内容(图片.javascript文件.css文件等),它决定了apache可以缓存多少内容,它缓存的内容越多,在硬盘上读取内容的机会就越少,而存取硬盘上的特定文件是一件很费时的操