我有这个java http客户端代码:
private void init(String[] args) {
setServerVersion(args);
commonParallelGenerator.setInputFlavor();
commonParallelGenerator.setNumberOfThreads("25"); //machine has 31 cores.
}
...
Report report = requestsList
.parallelStream()
.map(request -> freshResultsGenerator.getResponse(request, e2EResultLongBL))
...
//最终使用此 http 客户端:
import org.apache.http.StatusLine;
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.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import com.google.common.base.Stopwatch;
import com.google.common.base.Strings;
import com.google.inject.Inject;
public class RoutingUrlHttpClient implements IRoutingUrlHttpClient {
final static Logger logger = Logger.getLogger(RoutingUrlHttpClient.class);
private IRoutingResponseFromStringFetcher routingResponseParser;
private IRoutingResponseConverter routingResponseConverter;
private IUrlUtils urlUtils;
private CloseableHttpClient client;
private ILogUtils logUtils;
@Inject
@Singleton
public RoutingUrlHttpClient(IRoutingResponseFromStringFetcher routingResponseParser,
IRoutingResponseConverter routingResponseConverter, IUrlUtils urlUtils,
ILogUtils logUtils) {
this.routingResponseParser = routingResponseParser;
this.routingResponseConverter = routingResponseConverter;
this.urlUtils = urlUtils;
this.logUtils = logUtils;
RequestConfig requestConfig = RequestConfig.custom()
//time till handshake
.setConnectTimeout(40 * 1000)
//happens when you have a pool of connections and they are all busy, not allowing the connection
// manager to give you one connection to make the request.
.setConnectionRequestTimeout(40 * 1000)
//time till response
.setSocketTimeout(40 * 1000)
.build();
client = HttpClientBuilder
.create()
.setDefaultRequestConfig(requestConfig)
.build();
}
private CompleteRoutingResponseDtoWrapper sendRoutingRequestString(int numberOfTriesLeft,
String routingRequestUrl) {
routingRequestUrl = urlUtils.getHttpUrl(routingRequestUrl);
CompleteRoutingResponseDtoWrapper answer = new CompleteRoutingResponseDtoWrapper();
CloseableHttpResponse response = null;
try {
logger.debug("before sending http");
Stopwatch stopWatch = Stopwatch.createStarted();
response = client.execute(new HttpGet(routingRequestUrl));
stopWatch.stop();
// String latencyMsg = "after sending http. client-latency: "+stopWatch.elapsed(TimeUnit.MILLISECONDS) +" server-latency: "+response.getHeaders("Latency")[0].getValue();
logUtils.addLongToLongStatisticCollector("http.client.latency", (int)stopWatch.elapsed(TimeUnit.MILLISECONDS));
logUtils.addLongToLongStatisticCollector("http.server.latency", Integer.parseInt(response.getHeaders("Latency")[0].getValue()));
answer = analyzeStatusCodeAndMsgBody(numberOfTriesLeft, routingRequestUrl, answer, response, stopWatch);
} catch (Exception e) {
// e.printStackTrace();
// System.out.println(e.getMessage());
answer.errorMsg = e.getMessage();
answer.latency = null;
}
handleNullResponse(answer);
return answer;
}
我经常收到错误:
Timeout waiting for connection from pool
当我收到来自这个想法的请求时,
但是当我导航抛出浏览器时导航效果很好
你认为我应该在哪里调查瓶颈?
问题是我没有关闭 httpClient
//try-with-resources
try (CloseableHttpClient client = HttpClientBuilder
.create()
.setDefaultRequestConfig(requestConfig)
.build()){
response = client.execute(new HttpGet(routingRequestUrl));
stopWatch.stop();
// String latencyMsg = "after sending http. client-latency: "+stopWatch.elapsed(TimeUnit.MILLISECONDS) +" server-latency: "+response.getHeaders("Latency")[0].getValue();
logUtils.addLongToLongStatisticCollector("http.client.latency", (int)stopWatch.elapsed(TimeUnit.MILLISECONDS));
logUtils.addLongToLongStatisticCollector("http.server.latency", Integer.parseInt(response.getHeaders("Latency")[0].getValue()));
answer = analyzeStatusCodeAndMsgBody(numberOfTriesLeft, routingRequestUrl, answer, response, stopWatch);
}
关闭客户端可以解决问题,但是如果您在每次调用后关闭客户端,则不会重复使用连接,也不会使用连接池。
我宁愿确保您关闭 HttpResponse,它将连接返回到池中。
try (CloseableHttpResponse response = client2.execute(get))
{
response.getStatusLine();
// ..... read response and such
}
有关更多详细信息,请参阅 https://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html。
当然,您必须小心池配置,因为默认配置默认情况下每个路由仅设置 2 个连接(这可能有点低)。