Java 11 HttpClient导致无休止的SSL循环

时间:2019-02-01 19:07:47

标签: java multithreading http http2 java-11

我正在通过java.net.http.HttpClient方法使用 new sendAsyncHttpClient位于Singelton内部,并且像这样一次创建: HttpClient.newBuilder().build()真的没什么特别的。

这些请求可以是POSTGET,但我不知道是什么引起了麻烦。

每天只有几个请求,但是有时一个线程会占用100%的cpu内核。并且不是很快,而是在请求完成后的一段时间。

所以当甚至有两个无限循环发生时,我进行了一次线程转储,以下两个线程脱颖而出:

"HttpClient-4-Worker-5" #144 daemon prio=5 os_prio=0 cpu=511298.10ms elapsed=520.71s tid=0x00007f684403e800 nid=0x2d6b runnable  [0x00007f68ac162000]
   java.lang.Thread.State: RUNNABLE
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer.processData(java.net.http@11.0.2/SSLFlowDelegate.java:771)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer$WriterDownstreamPusher.run(java.net.http@11.0.2/SSLFlowDelegate.java:645)
        at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(java.net.http@11.0.2/SequentialScheduler.java:147)
        at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(java.net.http@11.0.2/SequentialScheduler.java:198)
        at jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(java.net.http@11.0.2/SequentialScheduler.java:271)
        at jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(java.net.http@11.0.2/SequentialScheduler.java:224)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer.triggerWrite(java.net.http@11.0.2/SSLFlowDelegate.java:722)
        at jdk.internal.net.http.common.SSLFlowDelegate.doHandshake(java.net.http@11.0.2/SSLFlowDelegate.java:1024)
        at jdk.internal.net.http.common.SSLFlowDelegate.doClosure(java.net.http@11.0.2/SSLFlowDelegate.java:1094)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader.unwrapBuffer(java.net.http@11.0.2/SSLFlowDelegate.java:500)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData(java.net.http@11.0.2/SSLFlowDelegate.java:389)
        - locked <0x00000000fba68950> (a java.lang.Object)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreamPusher.run(java.net.http@11.0.2/SSLFlowDelegate.java:263)
        at jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(java.net.http@11.0.2/SequentialScheduler.java:175)
        - locked <0x00000000fbbca3e8> (a java.lang.Object)
        at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(java.net.http@11.0.2/SequentialScheduler.java:147)
        at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(java.net.http@11.0.2/SequentialScheduler.java:198)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@11.0.2/ThreadPoolExecutor.java:1128)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@11.0.2/ThreadPoolExecutor.java:628)
        at java.lang.Thread.run(java.base@11.0.2/Thread.java:834)

   Locked ownable synchronizers:
        - <0x00000000fc1ff920> (a java.util.concurrent.ThreadPoolExecutor$Worker)





"HttpClient-4-Worker-2" #82 daemon prio=5 os_prio=0 cpu=4266156.67ms elapsed=4311.42s tid=0x00007f6844007000 nid=0x29ee runnable  [0x00007f686fffd000]
   java.lang.Thread.State: RUNNABLE
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer.processData(java.net.http@11.0.2/SSLFlowDelegate.java:771)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer$WriterDownstreamPusher.run(java.net.http@11.0.2/SSLFlowDelegate.java:645)
        at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(java.net.http@11.0.2/SequentialScheduler.java:147)
        at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(java.net.http@11.0.2/SequentialScheduler.java:198)
        at jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(java.net.http@11.0.2/SequentialScheduler.java:271)
        at jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(java.net.http@11.0.2/SequentialScheduler.java:224)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer.triggerWrite(java.net.http@11.0.2/SSLFlowDelegate.java:722)
        at jdk.internal.net.http.common.SSLFlowDelegate.doHandshake(java.net.http@11.0.2/SSLFlowDelegate.java:1024)
        at jdk.internal.net.http.common.SSLFlowDelegate.doClosure(java.net.http@11.0.2/SSLFlowDelegate.java:1094)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader.unwrapBuffer(java.net.http@11.0.2/SSLFlowDelegate.java:500)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData(java.net.http@11.0.2/SSLFlowDelegate.java:389)
        - locked <0x00000000f97668d0> (a java.lang.Object)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreamPusher.run(java.net.http@11.0.2/SSLFlowDelegate.java:263)
        at jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(java.net.http@11.0.2/SequentialScheduler.java:175)
        - locked <0x00000000f97668f0> (a java.lang.Object)
        at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(java.net.http@11.0.2/SequentialScheduler.java:147)
        at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(java.net.http@11.0.2/SequentialScheduler.java:198)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@11.0.2/ThreadPoolExecutor.java:1128)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@11.0.2/ThreadPoolExecutor.java:628)
        at java.lang.Thread.run(java.base@11.0.2/Thread.java:834)

   Locked ownable synchronizers:
        - <0x00000000f9894cc0> (a java.util.concurrent.ThreadPoolExecutor$Worker)

相同的观察结果,但是在另一个只影响一个线程的容器上。

"HttpClient-3-Worker-2" #120 daemon prio=5 os_prio=0 cpu=1100568.51ms elapsed=1113.79s tid=0x00007eff3003b800 nid=0x479 runnable  [0x00007eff83bf8000]
   java.lang.Thread.State: RUNNABLE
        at sun.security.ssl.SSLEngineImpl.wrap(java.base@11.0.1/SSLEngineImpl.java:136)
        - eliminated <0x00000000f9796e08> (a sun.security.ssl.SSLEngineImpl)
        at sun.security.ssl.SSLEngineImpl.wrap(java.base@11.0.1/SSLEngineImpl.java:116)
        - locked <0x00000000f9796e08> (a sun.security.ssl.SSLEngineImpl)
        at javax.net.ssl.SSLEngine.wrap(java.base@11.0.1/SSLEngine.java:519)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer.wrapBuffers(java.net.http@11.0.1/SSLFlowDelegate.java:821)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer.processData(java.net.http@11.0.1/SSLFlowDelegate.java:736)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer$WriterDownstreamPusher.run(java.net.http@11.0.1/SSLFlowDelegate.java:645)
        at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(java.net.http@11.0.1/SequentialScheduler.java:147)
        at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(java.net.http@11.0.1/SequentialScheduler.java:198)
        at jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(java.net.http@11.0.1/SequentialScheduler.java:271)
        at jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(java.net.http@11.0.1/SequentialScheduler.java:224)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer.triggerWrite(java.net.http@11.0.1/SSLFlowDelegate.java:722)
        at jdk.internal.net.http.common.SSLFlowDelegate.doHandshake(java.net.http@11.0.1/SSLFlowDelegate.java:1024)
        at jdk.internal.net.http.common.SSLFlowDelegate.doClosure(java.net.http@11.0.1/SSLFlowDelegate.java:1094)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader.unwrapBuffer(java.net.http@11.0.1/SSLFlowDelegate.java:500)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData(java.net.http@11.0.1/SSLFlowDelegate.java:389)
        - locked <0x00000000f9797010> (a java.lang.Object)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreamPusher.run(java.net.http@11.0.1/SSLFlowDelegate.java:263)
        at jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run(java.net.http@11.0.1/SequentialScheduler.java:175)
        - locked <0x00000000f9797030> (a java.lang.Object)
        at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(java.net.http@11.0.1/SequentialScheduler.java:147)
        at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(java.net.http@11.0.1/SequentialScheduler.java:198)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@11.0.1/ThreadPoolExecutor.java:1128)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@11.0.1/ThreadPoolExecutor.java:628)
        at java.lang.Thread.run(java.base@11.0.1/Thread.java:834)

我正在使用的一些示例代码

httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                                .thenApply(logResponse());

Java版本

openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment (build 11.0.2+9-Debian-3)
OpenJDK 64-Bit Server VM (build 11.0.2+9-Debian-3, mixed mode, sharing)

首选HTTP 2时也会发生此问题

更新

我使用HttpClient的方式有误吗? 这可能是服务器问题吗? 可能是这个错误https://bugs.openjdk.java.net/browse/JDK-8207009吗?

  • 客户端连接到cloudflare服务
  • 问题发生时,没有通过netstat可见的与cloudflare的开放连接
  • 我可以将问题固定到http2 + tlsv1.3(使用启用了tls1.3的nginx码头镜像:nginx:1.15-alpine

4 个答案:

答案 0 :(得分:5)

我遇到了同样的问题,发现 bug report

正在等待JDK 11.0.8发布。

答案 1 :(得分:4)

尝试禁用TLSv1.3SSLv3,以查看是否有帮助。

在命令行上设置系统属性:-Djdk.tls.disabledAlgorithms=TLSv1.3

或在<java_home>/conf/security/java.security

中定义属性

如果您认为这是实施错误,则可能要打开一个问题。

答案 2 :(得分:3)

如@jspcal所述,在禁用TLS 1.3之前。

tl; dr :通过扩展/覆盖禁用tlsv1.3

<java_home>/conf/security/java.security jdk.tls.disabledAlgorithms属性

由于我的应用程序正在docker容器中运行,因此我将基本映像更改为禁用tls1.3

FROM openjdk:11-jre
...

RUN sed -i "/jdk.tls.disabledAlgorithms=/ s/=.*/=TLSv1.3, SSLv3, RC4, MD5withRSA, DH keySize < 1024, EC keySize < 224, DES40_CBC, RC4_40, 3DES_EDE_CBC/" $(readlink -f /usr/bin/java | sed "s:bin/java::")/conf/security/java.security

据我所知,无法通过系统属性设置此(安全性)属性!另请参阅sun.security.util.DisabledAlgorithmConstraints#PROPERTY_TLS_DISABLED_ALGS,它实际上已准备好该属性。

答案 3 :(得分:0)

该错误已针对 11.0.10 Java 版本修复。