目录
一、描述
二、源码
三、结论
一、描述
验证一下CloseableHttpClient 在单例模式下并发量上涨是否会产生未知的问题,同时使用连接池减少测试案例的响应时间
二、源码
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** Title:* Description:* author :xbl* Date:2021/8/30* Time:15:43*/
@Slf4j
public class HttpUtilTest {private static PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();private static CloseableHttpClient httpClient = null;static {connectionManager.setMaxTotal(500);connectionManager.setDefaultMaxPerRoute(100);httpClient = HttpClients.custom().setConnectionManager(connectionManager).setDefaultRequestConfig(RequestConfig.custom().build()).build();}public static String doGet(String restUrl) {HttpGet httpGet = new HttpGet(restUrl);httpGet.setHeader("Content-type", "application/json");String responseBody = null;CloseableHttpResponse response = null;try {response = httpClient.execute(httpGet);if (response != null && response.getEntity() != null) {responseBody = EntityUtils.toString(response.getEntity());}} catch (ClientProtocolException e1) {log.error("【HttpUtil】-doGet-ClientProtocolException-" + e1.getMessage());} catch (IOException e1) {log.error("【HttpUtil】-doGet-IOException-" + e1.getMessage());} finally {if (response != null) {try {response.close();} catch (IOException e) {log.error("【HttpUtil】-doGet-response.close()-IOException" + e.getMessage());}}}return responseBody;}public static void testPool() {int c = 100;final CountDownLatch countDownLatch = new CountDownLatch(c);ExecutorService executorService = Executors.newFixedThreadPool(c);try {for (int i = 1; i <= c; i++) {executorService.submit(new Runnable() {@SneakyThrows@Overridepublic void run() {try {countDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("=========" + Thread.currentThread().getId());testReq();}});countDownLatch.countDown();}executorService.shutdown();} catch (Exception e) {e.printStackTrace();}}private static void testReq() {String result = HttpUtilTest.doGet("http://localhost:8080/healthycheck");System.out.println(result);}public static void main(String[] args) {testPool();}
}
三、结论
1.直接创建httpclient实例时,对其进行并发量分别为10、100的压测,发现其能够完成正常请求与响应,不过响应结果是串行的,并发数提升时,整个测试的时间会变长,说明它内部对请求并发数做了限制,并发量变大并不会导致问题产生,只会让它变慢。
private static CloseableHttpClient httpClient = HttpClients.createDefault();
2.通过PoolingHttpClientConnectionManager指定连接池进行并发数为100的压测时,能保证并发数为100并且立即并行响应,并发量颇大被httpclient阻塞时,可使用本方案。
private static PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();private static CloseableHttpClient httpClient = null;static {connectionManager.setMaxTotal(500);connectionManager.setDefaultMaxPerRoute(100);httpClient = HttpClients.custom().setConnectionManager(connectionManager).setDefaultRequestConfig(RequestConfig.custom().build()).build();}