java-httpasyncclient使用记录
这是几年前写的旧文,此前发布Wordpress小站上,现在又重新整理。算是温故知新,后续会继续整理。如有错误望及时指出,在此感谢。
随着线上业务量不断增加,会对原来的技术框架带来不小的挑战,这里记录一次线上HTTP服务调优的过程。
业务场景描述
产品A
提供了一个http接口服务,用来处理数据请求;
产品B
小菜,按照产品A的接口要求,把数据发送给产品A的接口服务处理;
....................
小菜:这个我熟,httpclient大法,走你...
public static int post(final String url, final Header[] headers, final HttpEntity entiry) throws IOException {
int statusCode = -1;
HttpResponse httpResponse = null;
try {
if (httpPost == null || httpPost.isAborted()) {
httpPost = new HttpPost(url);
}
if (headers != null && headers.length > 0) {
httpPost.setHeaders(headers);
}
if (entiry != null) {
httpPost.setEntity(entiry);
httpResponse = httpClient.execute(httpPost);
if (Objects.nonNull(httpResponse)) {
HttpEntity httpEntity = httpResponse.getEntity();
statusCode = httpResponse.getStatusLine().getStatusCode();
return statusCode;
} else {
return -1;
}
}else{
return -1;
}
} catch (Exception e) {
logger.error("http post error", e);
throw e;
} finally {
if (httpResponse != null) {
EntityUtils.consumeQuietly(httpResponse.getEntity());
}
}
}
收工.走人....
....................................
(三个月后.....)
boss:小菜呀,现在业务量越来越大啦,数据处理不过来,你赶紧处理下....
小菜:没问题....
(白天....)
小菜:(我擦咧)数据量增加十倍不止,加线程,加并发,快,快...
(半夜....)
小菜:杂回事,不好使啊.赶紧翻翻httpclient文档.
小菜:(Pooling connection manager,嗯,连接池,安排,安排上...)
小菜:(咦,下面的HttpAsyncClient,这是什么东东...)
(老师说过,名字越长的越厉害,HttpClient VS HttpAsyncClient)那肯定后者更厉害,那就了解下...)
HttpAsyncClient may be of interest to anyone building HTTP-aware client applications based on asynchronous, event driven I/O model.
通过官网的描述,小菜了解到,原来HttpAsyncClient是对原来HttpClient的扩展,基于异步事件驱动的。总结下来就是性能更好,支持高并发场景。
等等,这不就是小菜正在找的嘛?
说干就干。
首先,HttpAsyncClient和HttpClient一样,都是线程安全的,所以在多线程情况下可以放心使用。
这是官网的例子:
CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault();
try {
// Start the client
httpclient.start();
// Execute request
final HttpGet request1 = new HttpGet("http://www.apache.org/");
Future<HttpResponse> future = httpclient.execute(request1, null);
// and wait until a response is received
HttpResponse response1 = future.get();
System.out.println(request1.getRequestLine() + "->" + response1.getStatusLine());
// One most likely would want to use a callback for operation result
final CountDownLatch latch1 = new CountDownLatch(1);
final HttpGet request2 = new HttpGet("http://www.apache.org/");
httpclient.execute(request2, new FutureCallback<HttpResponse>() {
public void completed(final HttpResponse response2) {
latch1.countDown();
System.out.println(request2.getRequestLine() + "->" + response2.getStatusLine());
}
public void failed(final Exception ex) {
latch1.countDown();
System.out.println(request2.getRequestLine() + "->" + ex);
}
public void cancelled() {
latch1.countDown();
System.out.println(request2.getRequestLine() + " cancelled");
}
});
latch1.await();
// In real world one most likely would also want to stream
// request and response body content
final CountDownLatch latch2 = new CountDownLatch(1);
final HttpGet request3 = new HttpGet("http://www.apache.org/");
HttpAsyncRequestProducer producer3 = HttpAsyncMethods.create(request3);
AsyncCharConsumer<HttpResponse> consumer3 = new AsyncCharConsumer<HttpResponse>() {
HttpResponse response;
@Override
protected void onResponseReceived(final HttpResponse response) {
this.response = response;
}
@Override
protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException {
// Do something useful
}
@Override
protected void releaseResources() {
}
@Override
protected HttpResponse buildResult(final HttpContext context) {
return this.response;
}
};
httpclient.execute(producer3, consumer3, new FutureCallback<HttpResponse>() {
public void completed(final HttpResponse response3) {
latch2.countDown();
System.out.println(request3.getRequestLine() + "->" + response3.getStatusLine());
}
public void failed(final Exception ex) {
latch2.countDown();
System.out.println(request3.getRequestLine() + "->" + ex);
}
public void cancelled() {
latch2.countDown();
System.out.println(request3.getRequestLine() + " cancelled");
}
});
latch2.await();} finally {
httpclient.close();
}
在实际项目中,我们会是多进程多线程场景,这块的使用我这里就多重复了,有其它网友比我总结的更好,这里只针对在高并发场景下,HttpClient VS HttpAsyncClient的性能做一次测试。
说下结论,不进行参数优化的场景下,HttpClient,单线程QPS能在80-100qps/s。
而HttpAsyncClient不进行参数优化的场景下,单线程QPS能在1000-1200qps/s。
优化部分参数后,参稳定在1300qps/s。
好啦,小菜把代码优化以后,重新部署后,数据积压问题解决了。
睡觉喽。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!