httpclient4.3、httppool远程调用

概述

http

http客户端调用apachehttp工具包,基于httpclient4.3(org.apache.http.impl.client)开发,针对http请求相关业务需求进行封装。
        在网络协议中,http协议属于应用层协议,主要聚焦在规范数据层面,定义报文规则,使接收方能正确解析和响应,而在应用层下面的传输层,主要聚焦数据传输层面,包括tcp、ftp协议。http请求(连接)最终必须绑定到一个tcp连接进行上下行传输。传统http请求流程,为收到http请求,封装http报文,建立tcp连接,传输数据,收到响应,断开tcp连接,请求完成,每次请求都要新建一个tcp连接(传说中的三次握手四次挥手)。

http连接池

       PoolingHttpClient是传输层tcp连接。接收到http后,包装http报文,在发送时,从连接池中获取一个tcp连接进行传输,传输完毕后不关闭tcp连接,而是归还给连接池,由连接池维护tcp连接的生命周期,从而实现tcp连接的复用,减少系统和服务端频繁建立tcp连接的消耗,在高并发时这个损耗比较大(频繁握手挥手浪费资源)。另一方面,在高并发时,通过连接池可以有效的减少并发tcp连接数,减少客户端服务监听端口消耗,监听端口数量是有限,从而提高系统吞吐量,用少量tcp连接处理大量http请求,增加处理性能。最后,对于服务端,并发的tcp连接减少了,减少了服务端处理并发峰值压力,增加服务端稳定性。

      查看源码发现都在实现ConnectionSocketFactory的创建socket连接。

 

如下实例:

maxTotalPool

创建http连接池最大总连接数。

MAX_TIMEOUT

建立连接超时时间,创建tcp连接的超时时间。调小这个值,可以有效减少异常请求地址对连接的占用,将连接留给质量好的请求。

RequestTimeout

从连接池中获取连接的超时时间,即等待ConnectionManager释放connection的时间。在高并发情况下,连接池会不断创建新的连接,直到达到连接池最大连接数,此时连接池中已无空闲连接情况下,新的获取连接请求会处于等待状态,这个参数就是设置等待超时时间。调小这个时间,可以有效的提高响应速度并降低积压请求量,但是会增加请求失败概率。
 

SocketTimeout

响应超时时间,两次响应之间间隔时间,对于一般请求只有一次响应,为服务端响应超时时间,对处理时间较长的接口,需要调整此值。调小此连接也可以提高响应速度,增加系统吞吐,会增加异常请求概率,如有需要,需使用重发机制,此时服务端要考虑幂等处理。

如下为httppoolutil工具类:

package com.using.judge.web.client.utils;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.stereotype.Component;

@Component
public class HttpPoolUtil {

	private static Log logger = LogFactory.getLog(HttpPoolUtil.class); 

	public static final String UTF8 = "UTF-8"; 
	//默认打开的
	public static volatile boolean isClosed = false; 

	//连接池大小
	public static final int maxTotalPool = 30; 
	//最大超时时间
	public static final int MAX_TIMEOUT = 5000;
	//连接池获取实例时间
	public static final int RequestTimeout = 2000;

	private static RequestConfig requestConfig; 
	private static HttpClientBuilder httpClientBuilder; 
	private static PoolingHttpClientConnectionManager poolConnManager;
	static {
		// 设置连接池 
		poolConnManager = new PoolingHttpClientConnectionManager(); 
		poolConnManager.setMaxTotal(maxTotalPool);//设置连接池大小 
		poolConnManager.setDefaultMaxPerRoute(maxTotalPool); 
	
		RequestConfig.Builder configBuilder = RequestConfig.custom(); 
		// 设置连接超时 
		configBuilder.setConnectTimeout(MAX_TIMEOUT); 
		// 设置读取超时 
		configBuilder.setSocketTimeout(MAX_TIMEOUT); 
		// 设置从连接池获取连接实例的超时 
		configBuilder.setConnectionRequestTimeout(RequestTimeout); 
		// 在提交请求之前 测试连接是否可用 
		//configBuilder.setStaleConnectionCheckEnabled(true);
		requestConfig = configBuilder.build(); 
		// 
		httpClientBuilder = HttpClients.custom().setConnectionManager(poolConnManager).setDefaultRequestConfig(requestConfig); 
		logger.info(">>>>>>>>>>> PoolingHttpClientConnectionManager初始化成功 >>>>>>>>>>>"); 
	}/** 
	* 从http连接池里获取客户端实例 
	* @return httpClient 
	*/ 
	public static CloseableHttpClient getHttpClient() { 
		CloseableHttpClient httpClient = httpClientBuilder.build(); 
		if( null == httpClient ){ 
			logger.info("---------HttpClients.createDefault()---------"); 
			httpClient = HttpClients.createDefault(); 
		}

		return httpClient; 
	}/** 
	* 关闭连接池资源 
	*/ 
	public synchronized static void closePool() { 
		if( !isClosed ){ 
			isClosed = true; 
			poolConnManager.close(); 
		} 
	}
}

消费http连接池的实例

public File returnFileHttpPool(String urlStr, String fileName, String savePath) throws IOException {
			//拿到连接池
			CloseableHttpClient httpClient =  HttpPoolUtil.getClient();
			CloseableHttpResponse response=null;
			try {
				//执行get请求 
				response = httpClient.execute(new HttpGet(urlStr));
				if(response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
	            	log.debug("http 请求错误,错误码:"+response.getStatusLine().getStatusCode());
	            	return null;
	            }
				//获取响应消息内容
				InputStream inputStream = response.getEntity().getContent();
				// 获取自己数组
				byte[] getData = readInputStream(inputStream);
				// 文件保存位置
				File saveDir = new File(savePath);
				if (!saveDir.exists()) {
					saveDir.mkdir();
				}
				File file = new File(saveDir + File.separator + fileName);
				FileOutputStream fos = new FileOutputStream(file);
				fos.write(getData);
				if (fos != null) {
					fos.close();
				}
				if (inputStream != null) {
					inputStream.close();
				}
				return file;
			} catch (Exception e) {
				log.info("调用"+urlStr+"出错:"+e.getMessage());
			}				
			return null;
		}

消费http实例:

//获取httpclient
HttpClient client = new DefaultHttpClient();

详细阅读了关于tcp/ip协议,参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值