HttpClient 4.4 挂起任何请求

HttpClient 4.4 hangs on any request

我遇到 Apache HttpClieint 4.4 在任何请求上挂起的问题,即使基于 java.net.URL 的简单解决方案可以很好地检索相同的资源。

给定以下 HttpClient 配置:

RequestConfig requestConfig = RequestConfig.custom()
        .setExpectContinueEnabled(false)
        .setCookieSpec(CookieSpecs.DEFAULT)
        .setRedirectsEnabled(false)
        .setSocketTimeout(5000)
        .setConnectTimeout(5000)
        .setConnectionRequestTimeout(5000)
        .setStaleConnectionCheckEnabled(true)
        .build();

RegistryBuilder<ConnectionSocketFactory> connRegistryBuilder = RegistryBuilder.create();
connRegistryBuilder.register("http", PlainConnectionSocketFactory.INSTANCE);
try { // Fixing: https://code.google.com/p/crawler4j/issues/detail?id=174
    // By always trusting the ssl certificate
    SSLContext sslContext = SSLContexts.custom()
            .loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(final X509Certificate[] chain, String authType) {
                    return true;
                }
            }).build();
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    connRegistryBuilder.register("https", sslsf);
} catch (KeyManagementException | KeyStoreException | NoSuchAlgorithmException e) {
    LOGGER.warn("Exception thrown while trying to register https");
    LOGGER.debug("Stacktrace", e);
}

Registry<ConnectionSocketFactory> connRegistry = connRegistryBuilder.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(connRegistry);
connectionManager.setMaxTotal(5);
connectionManager.setDefaultMaxPerRoute(5);

HttpClientBuilder clientBuilder = HttpClientBuilder.create();
clientBuilder.setDefaultRequestConfig(requestConfig);
clientBuilder.setConnectionManager(connectionManager);
clientBuilder.setUserAgent("Cognitio");

HttpClient httpClient = clientBuilder.build();

下面的 HttpClient 请求挂起有什么充分的理由吗?

HttpGet request = new HttpGet("http://whosebug.com/");
request.setConfig(requestConfig);
HttpResponse response = httpClient.execute(request);

以下 java.net.URL 解决方案没有问题:

URL url = new URL("http://whosebug.com");
BufferedReader in = new BufferedReader(
new InputStreamReader(url.openStream()));

String inputLine;
while ((inputLine = in.readLine()) != null)
    System.out.println(inputLine);
in.close();

当我用日志语句轰炸我的应用程序时,我确定它挂在 httpClient.execute 部分,尽管指定了超时,但未能超时。此外,我将 SLF4J 与 JCL 桥一起使用,但是当我将其设置为调试时,我没有收到 org.apache.http 的日志条目。不确定这是否符合预期。

非常感谢任何帮助!

此问题是由 org.codehaus.mojo:exec-maven-plugin 中的一个小问题引起的。

也就是说,当你设置 <includePluginDependencies>true</includePluginDependencies> 时,你也会得到插件的 SLF4J 依赖项,并且它们不能被排除在我所看到的之外。解决这个问题的简单方法是首先在插件依赖项部分声明 SLF4J/Logback 依赖项。

我发现不需要再次声明 slf4j-api,在我的例子中只需声明 logback-classic 和 jcl-over-slf4j。