【问题标题】:Quite frequent SSLPeerUnverifedException with PoolingClientConnectionManagerPoolingClientConnectionManager 频繁出现 SSLPeerUnverifedException
【发布时间】:2016-01-28 21:19:58
【问题描述】:

在我们使用 PoolingClientConnectionManager 4.2.1 的系统上(由于其他依赖关系,我们目前无法更新它)。

当有超过一定数量的请求时,我们开始为单个请求收到 SSLPeerUnverifiedExceptions,我目前无法弄清楚原因,也是因为某些 Javadoc 仅显示“已弃用”。

这是池的设置:

SchemeRegistry schemeRegistry = SchemeRegistryFactory.createDefault();
Scheme https = getHttpsScheme(sslContext, port);
schemeRegistry.register(https);

PoolingClientConnectionManager connectionManager =
            new PoolingClientConnectionManager(schemeRegistry, 5000, TimeUnit.MILLISECONDS);
connectionManager.setMaxTotal(20);
connectionManager.setDefaultMaxPerRoute(20);

return new DefaultHttpClient(connectionManager);

这里是日志:

尝试工作: PoolingClientConnectionManager "Connection request: [route: {s}->@987654321@ kept alive: 20; route allocated: 20 of 20; total allocated: 20 of 20]" DefaultClientConnection "Connection 0.0.0.0:49954<->[server_ip]:443 closed" PoolingClientConnectionManager "Connection leased: [id: 94198][route: {s}->@987654322@ kept alive: 19; route allocated: 20 of 20; total allocated: 20 of 20]" DefaultClientConnectionOperator "Connecting to myserver:443"

尝试失败: PoolingClientConnectionManager "Connection request: [route: {s}->@987654323@ ][total kept alive: 19; route allocated: 20 of 20; total allocated: 20 of 20]" DefaultClientConnection "Connection 0.0.0.0:49953<->[server_ip]:443 closed" PoolingClientConnectionManager "Connection leased: [id: 94196][route: {s}->@987654324@ ][total kept alive: 18; route allocated: 20 of 20; total allocated: 20 of 20]" DefaultClientConnectionOperator "Connecting to myserver:443" DefaultClientConnection "Connection org.apache.http.impl.conn.DefaultClientConnection@4821fdeb closed" DefaultClientConnection "Connection org.apache.http.impl.conn.DefaultClientConnection@4821fdeb shut down" PoolingClientConnectionManager "Connection [id: 94196][route: {s}->@987654325@ ] can be kept alive for 9223372036854775807 MILLISECONDS" DefaultClientConnection "Connection org.apache.http.impl.conn.DefaultClientConnection@4821fdeb closed" PoolingClientConnectionManager "Connection released: [id: 94196][route: {s}->@987654326@ ][total kept alive: 18; route allocated: 19 of 20; total allocated: 19 of 20]"

除了如何摆脱异常,我想知道

  • 如果池很小,因为所有路由都是永久分配的
  • 如果我作为构造函数 arg(5000 毫秒)传递的生存时间得到尊重,当它说“可以保持活动 9223372036854775807 MILLISECONDS”时
  • 为什么连接在失败的尝试中被关闭。

【问题讨论】:

    标签: java ssl apache-httpclient-4.x


    【解决方案1】:

    通过在出现异常情况下提前关闭过期和空闲连接的情况下添加重试来解决问题。

    ...
        try {
            result = performWsRequest(request, soapAction);
        } catch (WebServiceIOException | SSLPeerUnverifiedException ex) {
            if (retryAttempt) {
                logAndThrowExceptionUponWsRequest(ex);
            } else {
                LOGGER.info("Re-trying webservice-request");
                cleanConnections();
                result = performWsRequestWithRetry(request, soapAction, true);
            }
        } catch (Exception e) {
            logAndThrowExceptionUponWsRequest(e);
        }
    ...
    
    private synchronized void cleanConnections() {
    
        LOGGER.info(
                "Cleaning connections. Total message-senders: {}",
                this.webServiceTemplate.getMessageSenders().length);
    
        for (WebServiceMessageSender messageSender : this.webServiceTemplate.getMessageSenders()) {
    
            if (messageSender instanceof HttpComponentsMessageSender) {
    
                LOGGER.info("Checking connections of message-sender {}", messageSender);
                HttpComponentsMessageSender httpComponentsMessageSender = (HttpComponentsMessageSender)messageSender;
    
                if (httpComponentsMessageSender.getHttpClient() != null
                    && httpComponentsMessageSender.getHttpClient().getConnectionManager() != null) {
                    LOGGER.info("Closing connections");
                    httpComponentsMessageSender.getHttpClient().getConnectionManager().closeExpiredConnections();
                    httpComponentsMessageSender.getHttpClient()
                            .getConnectionManager()
                            .closeIdleConnections(5000, TimeUnit.MILLISECONDS);
                }
            }
        }
    }
    

    【讨论】:

    • 原来问题是后端节点的证书导致重新协商失败。作为一种解决方法,jvm 参数已通过 -Djdk.tls.allowUnsafeServerCertChange=true 和 -Dsun.security.ssl.allowUnsafeRenegotiation=true 来丰富
    猜你喜欢
    • 2013-02-14
    • 2021-01-28
    • 1970-01-01
    • 2014-07-17
    • 2016-09-04
    • 1970-01-01
    • 2022-06-15
    • 1970-01-01
    • 2016-01-16
    相关资源
    最近更新 更多