项目中用到HttpClient比较多,公司使用的框架是Apache HttpClient,它是用BIO实现的,我想使用了NIO的Netty效率会不会好些。
在网上没有查到这两个性能对比,自己写了例子测试的。
Netty的原生HttpClient需要自己写连接池管理,我使用的是AsyncHttpClient。
测试的基类,30个线程并发发起请求,每个线程连续请求200次:
package com.weishubin.test.httpclient;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class AbstractHttpClientTester {
public static final int THREAD_COUNT = 30;//并行线程数量
public static final int TIMES = 200;//一个线程内执行的次数
public long mainStart;
public long[][] RECORD = new long[THREAD_COUNT][TIMES];//记录耗时
public AtomicInteger counter;
public ExecutorService executor = Executors.newCachedThreadPool();
public void run() {
createHttpClient();
counter = new AtomicInteger(0);
mainStart = System.currentTimeMillis();
for (int i = 0; i < THREAD_COUNT; i++) {
executor.submit(new Http(i));;
}
}
protected abstract void createHttpClient();
protected abstract String request() throws Exception;
protected void close() {
executor.shutdown();
}
public class Http extends Thread {
int index;
Http(int i) {
this.index = i;
}
public void run() {
test();
int r = counter.incrementAndGet();
if (r == THREAD_COUNT) {
printResult();
close();
}
}
private void test() {
for (int i = 0; i < TIMES; i++) {
long start = System.currentTimeMillis();
try {
String data = request();
//System.out.println(data);
RECORD[index][i] = System.currentTimeMillis() - start;
} catch (Exception e) {
e.printStackTrace();
RECORD[index][i] = 0;
}
}
}
private void printResult() {
long sum = 0;
long count = 0;
for (int i = 0; i < THREAD_COUNT; i++) {
for (int j = 0; j < TIMES; j++) {
if (RECORD[i][j] > 0) {
sum += RECORD[i][j];
count++;
}
}
}
System.out.println("TOTAL COST:" + (System.currentTimeMillis() - mainStart));
System.out.println("TIMES:" + TIMES);
System.out.println("SUCCESS COUNT:" + count);
System.out.println("AVG COST:" + sum / count);
}
}
}
Apache HttpClient测试类:
package com.weishubin.test.httpclient;
import java.io.IOException;
import org.apache.http.HttpHost;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.params.SyncBasicHttpParams;
public class ApacheHttpClientTester extends AbstractHttpClientTester {
public HttpClient httpClient;
public BasicResponseHandler handler;
public static void main(String[] args) {
new ApacheHttpClientTester().run();
}
@Override
protected void createHttpClient() {
PoolingClientConnectionManager cm = new PoolingClientConnectionManager();
cm.setMaxTotal(40);
cm.setDefaultMaxPerRoute(40);
HttpParams param = new SyncBasicHttpParams();
HttpProtocolParams.setVersion(param, HttpVersion.HTTP_1_1);
HttpConnectionParams.setTcpNoDelay(param, true);
HttpConnectionParams.setConnectionTimeout(param, 30000);
HttpConnectionParams.setSoTimeout(param, 30000);
httpClient = new DefaultHttpClient(cm);
httpClient.getParams().setParameter(ClientPNames.DEFAULT_HOST, new HttpHost("192.168.1.105", 8090));
handler = new BasicResponseHandler();
}
@Override
protected String request() throws ClientProtocolException, IOException {
HttpGet request = new HttpGet("/httpclient/get.json");
String r = httpClient.execute(request, handler);
//System.out.println(r);
return r;
}
}
package com.weishubin.test.httpclient;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.AsyncHttpClientConfig;
import com.ning.http.client.ListenableFuture;
import com.ning.http.client.providers.netty.response.NettyResponse;
public class AsyncHttpClientTester extends AbstractHttpClientTester {
public static void main(String[] args) {
new AsyncHttpClientTester().run();
}
private AsyncHttpClient httpClient;
@Override
protected void createHttpClient() {
AsyncHttpClientConfig.Builder cf = new AsyncHttpClientConfig.Builder();
cf.setConnectTimeout(3000);
cf.setConnectionTTL(3000);
cf.setPooledConnectionIdleTimeout(3000);
cf.setReadTimeout(3000);
AsyncHttpClientConfig config = cf.build();
httpClient = new AsyncHttpClient(config);
}
@Override
protected String request() throws Exception {
String url = "http://192.168.1.105:8090/httpclient/get.json";
ListenableFuture data = httpClient
.prepareGet(url).execute();
NettyResponse s = (NettyResponse) data.get();
return s.getResponseBody();
}
@Override
protected void close() {
super.close();
httpClient.closeAsynchronously();
}
}
服务是我自己写的一个Netty服务,简单的返回一个Json字符串。
多次测试发现两个性能没有明显差别。
又考虑到我们的并发量远没有达到30个,AsyncHttpClient也没有Apache实现得成熟,没有使用,继续使用了Apahce。