HttpClient:connection still allocated 完美处理

最近一个现场在使用应用访问SSO时频繁出现 Connection timed out: connect,导致应用卡顿,挂机频繁, 由于是使用了HttpClient。

后来查了查资料 此问题出现原因是并发调用同一个httpclient去请求数据。在上一个请求尚未结束时,又启新的线程再次使用该httpclient请求数据,因为 httpclient 我用的是一个静态常量 ,应用中只有一个,导致问题出现。

现在有2个解决方案:

  1. 加个synchronized,这个方法是避免了报错,以不会出现多个同时操作,同步大家 都知道 ,但有一个问题就是如果一个请求不通时,耗时是相当长,这样在要求多并发的应用中是不符的。

  2. 把httpclient 变成成员变量,每次使用的时候都初始化,用完了close关闭,这样解决了并发问题,但经过测试大概3000的并发吧,用多线程同时使用,再多由于网络原因PC机就已经断网了。

目前我的解决方法是用第2种把httpclient变成成员变量, 本人对httpclient不精通,有更好解决方法的大神,请不吝赐教!

分享一下代码:

    /** 
     * HTTP Get 获取内容 
     * @param url请求的url地址 ?之前的地址 
     * @param params请求的参数 
     * @return 页面内容 
     */  
    public static String sendGet(String url, Map<String, Object> params) throws ParseException, UnsupportedEncodingException, IOException{
        return sendGet(url, params,null);
    }
    public static String sendGet(String url, Map<String, Object> params,Map<String, Object>headers) throws ParseException, UnsupportedEncodingException, IOException{  

        if(params !=null && !params.isEmpty()){  

            List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());  

            for (String key :params.keySet()){  
                pairs.add(new BasicNameValuePair(key, params.get(key).toString()));  
            }  
            url +="?"+EntityUtils.toString(new UrlEncodedFormEntity(pairs), CHARSET);  
        }  

        HttpGet httpGet = new HttpGet(url);

        if (headers != null && !headers.isEmpty()) {                
            for (String key : headers.keySet()) {  
                httpGet.setHeader(key, headers.get(key).toString());
            }  
        }
        CloseableHttpClient httpClient = buildClient();
        CloseableHttpResponse response = httpClient.execute(httpGet);
        int statusCode = response.getStatusLine().getStatusCode();  
        if(statusCode !=200){  
            httpGet.abort();  
            throw new RuntimeException("HttpClient,error status code :" + statusCode);  
        }  
        HttpEntity entity = response.getEntity(); 
        String result = null;  
        if (entity != null) {  
            result = EntityUtils.toString(entity, "utf-8");  
            EntityUtils.consume(entity);  
            response.close();
            httpClient.close();
            return result;  
        }else{  
            return null;  
        }  
    }  

我把 buildClient() 方法也拿出来分享一下, 此方法已经适配了 适配X509证书

    /**
     * 适配X509证书
     * @return
     */
    private static CloseableHttpClient buildClient(){
        RequestConfig config = RequestConfig.custom().setConnectTimeout(-1).setSocketTimeout(-1).build();
        X509TrustManager tm = new X509TrustManager() {  

            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
            }  


            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
            }  

            public X509Certificate[] getAcceptedIssuers() {  
                return null;  
            }  
        }; 

        SSLContext ctx = null;  
        try {  
            ctx = SSLContext.getInstance("TLS");  
            ctx.init(null, new TrustManager[] { tm }, null);  
        } catch (KeyManagementException e) {  
            logger.debug("context", e);
        } catch (NoSuchAlgorithmException e) {    
            logger.debug("context", e);
        } 

        HttpClientBuilder builder = HttpClientBuilder.create();



        SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(ctx,  
                NoopHostnameVerifier.INSTANCE);  
        builder.setSSLSocketFactory(sslConnectionFactory);  

        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()  
                .register("https", sslConnectionFactory).register("http", PlainConnectionSocketFactory.getSocketFactory()).build();  

        HttpClientConnectionManager ccm1 = new BasicHttpClientConnectionManager(registry);  

        builder.setConnectionManager(ccm1);

        return builder.setDefaultRequestConfig(config).build();  

    }
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值