httpclient中警告Encrypted Alert后断开连接问题处理

       工作中需要对接某第三方支付公司,其对外提供https服务(不需要证书),8583报文。生产环境下,近期忽然出现超时的情况,表现是程序抛出异常java.net.SocketTimeoutException: Read timed out。查看日志,发现才5秒时间,没有到超时时间,找上游沟通,反馈说是1秒正常返回了。

        首先怀疑是网络问题,由于是互联网对接,网络问题不好确认,于是用tcpdump在系统中抓包观察,发现以下问题:httpclient中警告Encrypted Alert后断开连接问题处理_第1张图片,服务端通知客户端Encrypted Alert(没有发数据),客户端断开连接。由此可知不是网络问题。

       再次和上游确认,上游系统用到httpclient4.3,客户端使用httpclient3.1,考虑可能是该问题导致,于是升级客户端版本,改造程序如下:

private String writePost(String url, String content) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
            SSLContext sslContext = SSLContexts.custom().useTLS().loadTrustMaterial(null, new TrustStrategy() {
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();

        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new AllowAllHostnameVerifier());

        Registry r = RegistryBuilder.create()
                .register("https", sslConnectionSocketFactory)
                .build();
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(r);
        cm.setMaxTotal(500);
        cm.setDefaultMaxPerRoute(350);

        SocketConfig socketConfig = SocketConfig.custom()
                .setSoKeepAlive(true)
                .setTcpNoDelay(true)
                .setSoTimeout(timeout)
                .build();
        cm.setDefaultSocketConfig(socketConfig);

        RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeout).setConnectTimeout(timeout).setSocketTimeout(timeout).build();

        //创建httpClient
        CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(cm)
                .setDefaultRequestConfig(requestConfig)
                .build();
        HttpPost httpPost = new HttpPost(url);

        String response="";
        try {
            if (null != content) {
                byte[] bs= hexConvert.str10Bcd(content);
                ByteArrayEntity arrayEntity = new ByteArrayEntity(bs);
                httpPost.setEntity(arrayEntity);
            }
            CloseableHttpResponse result = httpClient.execute(httpPost);
            //请求发送成功,并得到响应
            log.info("httpstatus:"+result.getStatusLine().getStatusCode());
            if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                try {
                    HttpEntity entity = result.getEntity();
                    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
                    InputStream inputStream = entity.getContent();
                    int chunk=0;
                    byte[] tmp = new byte[4096];
                    while ((chunk = inputStream.read(tmp)) != -1) {
                        buffer.write(tmp, 0, chunk);
                    }
                    byte[] stuff = buffer.toByteArray();
                    response = hexConvert.byte2HexString(stuff);
                } catch (Exception e) {
                    log.error("post请求提交失败:" + url, e);
                }
            }
        } catch (Exception e) {
            log.info("执行Post请求" + url + "时,发生异常!"+ e);
        } finally {
            httpPost.releaseConnection();
        }
        return response;
    }

改造完成后每笔交易都会有Encrypted Alert,但是数据正常获取到,使用到的协议已经变成了TLSV1.2,升级前使用TLSV1.1,正常交易没有Encrypted Alert,异常交易才会有Encrypted Alert。

转载于:https://my.oschina.net/zfjzy/blog/1518830

你可能感兴趣的:(httpclient中警告Encrypted Alert后断开连接问题处理)