我們原來用的httpClient一直都是com.ning.http.client.AsyncHttpClient(線程池管理類),需要的時候申請,不需要的時候釋放。并發比較高的情況下,存在http連結不釋放的問題,更新了版本也解決不了,我最近對它進行了一次重構,徹底解決了這個問題
替換的思路就是用ThreadLocal來為每一個線程配置設定一個HttpClient,使用後自己釋放連結,這樣每個線程就不用重複構造HttpClient。同時為了盡可能減少記憶體的申請,為在函數調用過程中申請的變量都申請了ThreadLocal變量,demo如下
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URLDecoder;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings("deprecation")
public class HttpClient {
private static final Logger log = LoggerFactory.getLogger(HttpClient.class);
private static ThreadLocal<org.apache.commons.httpclient.HttpClient> threadHttpClient = new ThreadLocal<org.apache.commons.httpclient.HttpClient>();
private static ThreadLocal<PostMethod> threadPostMethod = new ThreadLocal<PostMethod>();
private static ThreadLocal<GetMethod> threadGetMethod = new ThreadLocal<GetMethod>();
private static ThreadLocal<ByteArrayOutputStream> threadByteArrayOutputStream = new ThreadLocal<ByteArrayOutputStream>();
private static ThreadLocal<byte[]> threadByte = new ThreadLocal<byte[]>();
public static String doPost(String url, String requestJson) throws Exception {
org.apache.commons.httpclient.HttpClient client = getHttpClient();
PostMethod method = getPostMethod();
try {
URI base = new URI(url, false);
method.setURI(base);
method.setRequestBody(requestJson);
method.setRequestHeader("Content-Type", "application/json;charset=utf-8");
int result = client.executeMethod(method);
if (result == HttpStatus.SC_OK) {
InputStream in = method.getResponseBodyAsStream();
ByteArrayOutputStream baos = getByteArrayOutputStream();
byte[] buffer = getByte();
int len = 0;
while ((len = in.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
return URLDecoder.decode(baos.toString(), "UTF-8");
} else {
log.error("HTTP ERROR Status: " + method.getStatusCode() + ":" + method.getStatusText());
return null;
}
} finally {
method.releaseConnection();
}
}
public static String doGet(String url) throws Exception {
org.apache.commons.httpclient.HttpClient client = getHttpClient();
GetMethod method = getGetMethod();
try {
URI base = new URI(url, false);
method.setURI(base);
int result = client.executeMethod(method);
if (result == HttpStatus.SC_OK) {
InputStream in = method.getResponseBodyAsStream();
ByteArrayOutputStream baos = getByteArrayOutputStream();
byte[] buffer = getByte();
int len = 0;
while ((len = in.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
return URLDecoder.decode(baos.toString(), "UTF-8");
} else {
log.error("HTTP ERROR Status: " + method.getStatusCode() + ":" + method.getStatusText());
return null;
}
} finally {
method.releaseConnection();
}
}
private static org.apache.commons.httpclient.HttpClient getHttpClient() {
org.apache.commons.httpclient.HttpClient client = threadHttpClient.get();
if (client == null) {
client = new org.apache.commons.httpclient.HttpClient();
threadHttpClient.set(client);
log.info("new HttpClient");
}
return client;
}
private static PostMethod getPostMethod() {
PostMethod post = threadPostMethod.get();
if (post == null) {
post = new PostMethod();
threadPostMethod.set(post);
log.info("new PostMethod");
}
post.recycle();
return post;
}
private static GetMethod getGetMethod() {
GetMethod get = threadGetMethod.get();
if (get == null) {
get = new GetMethod();
threadGetMethod.set(get);
log.info("new GetMethod");
}
get.recycle();
return get;
}
private static ByteArrayOutputStream getByteArrayOutputStream() {
ByteArrayOutputStream get = threadByteArrayOutputStream.get();
if (get == null) {
get = new ByteArrayOutputStream();
threadByteArrayOutputStream.set(get);
log.info("new ByteArrayOutputStream");
}
get.reset();
return get;
}
private static byte[] getByte() {
byte[] get = threadByte.get();
if (get == null) {
get = new byte[1024];
threadByte.set(get);
log.info("new byte[]");
}
return get;
}
}