httpclient org.apache.http.NoHttpResponseException: host:端口 failed to respond 错误原因和解决方法

  • 原因:httpclient 之前与服务端建立的链接已经失效(例如:tomcat 默认的keep-alive timeout :20s),再次从连接池拿该失效链接进行请求时,就会保存。
  • 解决方法:官方链接:http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e659
  • 上面官方链接的2.6 解决方法的代码如果报错,可能是自己的httpclient版本 不适用。自己用的是httpclient 4.0.1,使用以下代码绿色代码:
    import com.google.api.client.http.ByteArrayContent;
    import com.google.api.client.http.GenericUrl;
    import com.google.api.client.http.HttpBackOffUnsuccessfulResponseHandler;
    import com.google.api.client.http.HttpContent;
    import com.google.api.client.http.HttpHeaders;
    import com.google.api.client.http.HttpRequest;
    import com.google.api.client.http.HttpRequestFactory;
    import com.google.api.client.http.HttpResponse;
    import com.google.api.client.http.HttpStatusCodes;
    import com.google.api.client.http.HttpTransport;
    import com.google.api.client.http.apache.ApacheHttpTransport;
    import com.google.api.client.util.BackOff;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ProxySelector;
    import java.util.Map;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.concurrent.TimeUnit;
    import javax.annotation.PreDestroy;
    import lombok.Data;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.http.HeaderElement;
    import org.apache.http.HeaderElementIterator;
    import org.apache.http.HttpHost;
    import org.apache.http.conn.ClientConnectionManager;
    import org.apache.http.conn.ConnectionKeepAliveStrategy;
    import org.apache.http.conn.params.ConnManagerParams;
    import org.apache.http.conn.params.ConnPerRouteBean;
    import org.apache.http.conn.scheme.PlainSocketFactory;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
    import org.apache.http.impl.conn.ProxySelectorRoutePlanner;
    import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
    import org.apache.http.message.BasicHeaderElementIterator;
    import org.apache.http.params.BasicHttpParams;
    import org.apache.http.params.HttpConnectionParams;
    import org.apache.http.params.HttpParams;
    import org.apache.http.protocol.HTTP;
    import org.apache.http.protocol.HttpContext;
    
    /**
     * @author Li Sheng
     */
    @Slf4j
    public class HttpClientUtils {
    
    
      private static HttpRequestFactory requestFactory;
      private static HttpTransport httpTransport;
      private static final String CONTENT_TYPE_JSON = "application/json";
    
      private static final int CACHE_SIZE = 4096;
    
    
      static {
    
        HttpParams params = new BasicHttpParams();
        HttpConnectionParams.setStaleCheckingEnabled(params, false);
        HttpConnectionParams.setSocketBufferSize(params, 245760); // 8k(8192) * 30
        ConnManagerParams.setMaxTotalConnections(params, 400);
        ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(200));
    
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
        ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(params, registry);
    
        DefaultHttpClient defaultHttpClient = new DefaultHttpClient(connectionManager, params);
        defaultHttpClient.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(0, false));
        defaultHttpClient
            .setRoutePlanner(new ProxySelectorRoutePlanner(registry, ProxySelector.getDefault()));
    
    
        ConnectionKeepAliveStrategy connectionKeepAliveStrategy = new ConnectionKeepAliveStrategy() {
          @Override
          public long getKeepAliveDuration(org.apache.http.HttpResponse httpResponse,
              HttpContext httpContext) {
            return 20 * 1000; // 20 seconds,because tomcat default keep-alive timeout is 20s
          }
        };
        defaultHttpClient.setKeepAliveStrategy(connectionKeepAliveStrategy);
    
        httpTransport = new ApacheHttpTransport(defaultHttpClient);
    
        requestFactory = httpTransport.createRequestFactory();
    
      }
    
      @Data
      public static class PostParam {
    
        private Integer connectTimeoutMills;  // 可选,默认 20s
        private Integer readTimeoutMills;  // 可选,默认 20s
        private Map<String, String> headers; // 可选
        private String url; //必填
        private String postJson; //必填
        private Boolean readResponseData; //必填:是否需要读取数据。如果不需要返回结果,设置 false
        private BackOff backOff; //可选,重试机制策略
        private String authorization; //可选
    
        public PostParam(String url, String postJson, boolean readResponseData) {
          this.url = url;
          this.postJson = postJson;
          this.readResponseData = readResponseData;
        }
      }
    
      public static String postWithJson(PostParam postParam) {
        GenericUrl genericUrl = new GenericUrl(postParam.getUrl());
        HttpContent httpContent = ByteArrayContent.fromString(null, postParam.getPostJson());
        HttpResponse httpResponse = null;
        try {
          HttpRequest httpRequest = requestFactory.buildPostRequest(genericUrl, httpContent);
          if (postParam.getConnectTimeoutMills() != null) {
            httpRequest.setConnectTimeout(postParam.getConnectTimeoutMills());
          }
          if (postParam.getReadTimeoutMills() != null) {
            httpRequest.setReadTimeout(postParam.getReadTimeoutMills());
          }
          if (postParam.getBackOff() != null) {
            httpRequest.setUnsuccessfulResponseHandler(
                new HttpBackOffUnsuccessfulResponseHandler(postParam.getBackOff()));
          }
    
          HttpHeaders httpHeaders = new HttpHeaders();
          httpHeaders.setContentType(CONTENT_TYPE_JSON);
          Map<String, String> headers = postParam.getHeaders();
          if (headers != null && headers.size() > 0) {
            headers.forEach(httpHeaders::set);
          }
          if (postParam.getAuthorization() != null && !postParam.equals("")) {
            httpHeaders.setAuthorization(postParam.getAuthorization());
          }
    
          httpRequest.setHeaders(httpHeaders);
          httpResponse = httpRequest.execute();
          if (httpResponse.getStatusCode() != HttpStatusCodes.STATUS_CODE_OK) {
            log.error("http status not 200. param:{},status:{},msg:{}", postParam,
                httpResponse.getStatusCode(), httpResponse.getStatusMessage());
            return null;
          }
          Boolean readResponseData = postParam.getReadResponseData();
          if (readResponseData != null && readResponseData) {
            InputStream inputStream = httpResponse.getContent();
            if (inputStream != null) {
              StringBuffer out = new StringBuffer();
              byte[] b = new byte[CACHE_SIZE];
              for (int n; (n = inputStream.read(b)) != -1; ) {
                out.append(new String(b, 0, n));
              }
              return out.toString();
            }
          }
        } catch (Exception e) {
          log.error("post exception,param:{}", postParam, e);
        } finally {
          try {
            if (httpResponse != null) {
              httpResponse.disconnect();
            }
          } catch (Exception e) {
            log.error("httpResponse disconnect exception", e);
          }
        }
        return null;
      }
    
      @PreDestroy
      public static void destory() {
        try {
          log.info("httpTransport shutdown now....");
          httpTransport.shutdown();
        } catch (IOException e) {
          log.error("shut down httpTransport exception", e);
        }
      }
    
    }

     

  • 如果想使用上面的 HttpClientUtils,必须引入 google-httpclient:
    •    <dependency>
              <groupId>com.google.http-client</groupId>
              <artifactId>google-http-client</artifactId>
              <version>1.22.0</version>
            </dependency>

       

posted @ 2017-10-11 20:29  java后端领域  阅读(62868)  评论(0编辑  收藏  举报