web-dev-qa-db-ja.com

java 11 HttpClientは無限のSSLループを引き起こします

newJava.net.http.HttpClientsendAsyncメソッドで使用しています。 HttpClientはSingelton内にあり、次のように1回作成されます。HttpClient.newBuilder().build()なので、特別なことは何もありません。

これらのリクエストはPOSTまたはGETの可能性がありますが、問題の原因はわかりません。

1日に数件のリクエストがありますが、時々1つのスレッドがCPUコアの100%を使用します。そして、差し迫ったわけではありませんが、要求が終了した後しばらくしてから。

そのため、無限ループが2つでも発生しているときにスレッドダンプを実行したところ、次の2つのスレッドが際立っていました。

"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([email protected]/SSLFlowDelegate.Java:771)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer$WriterDownstreamPusher.run([email protected]/SSLFlowDelegate.Java:645)
        at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run([email protected]/SequentialScheduler.Java:147)
        at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run([email protected]/SequentialScheduler.Java:198)
        at jdk.internal.net.http.common.SequentialScheduler.runOrSchedule([email protected]/SequentialScheduler.Java:271)
        at jdk.internal.net.http.common.SequentialScheduler.runOrSchedule([email protected]/SequentialScheduler.Java:224)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer.triggerWrite([email protected]/SSLFlowDelegate.Java:722)
        at jdk.internal.net.http.common.SSLFlowDelegate.doHandshake([email protected]/SSLFlowDelegate.Java:1024)
        at jdk.internal.net.http.common.SSLFlowDelegate.doClosure([email protected]/SSLFlowDelegate.Java:1094)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader.unwrapBuffer([email protected]/SSLFlowDelegate.Java:500)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData([email protected]/SSLFlowDelegate.Java:389)
        - locked <0x00000000fba68950> (a Java.lang.Object)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreamPusher.run([email protected]/SSLFlowDelegate.Java:263)
        at jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run([email protected]/SequentialScheduler.Java:175)
        - locked <0x00000000fbbca3e8> (a Java.lang.Object)
        at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run([email protected]/SequentialScheduler.Java:147)
        at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run([email protected]/SequentialScheduler.Java:198)
        at Java.util.concurrent.ThreadPoolExecutor.runWorker([email protected]/ThreadPoolExecutor.Java:1128)
        at Java.util.concurrent.ThreadPoolExecutor$Worker.run([email protected]/ThreadPoolExecutor.Java:628)
        at Java.lang.Thread.run([email protected]/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([email protected]/SSLFlowDelegate.Java:771)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer$WriterDownstreamPusher.run([email protected]/SSLFlowDelegate.Java:645)
        at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run([email protected]/SequentialScheduler.Java:147)
        at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run([email protected]/SequentialScheduler.Java:198)
        at jdk.internal.net.http.common.SequentialScheduler.runOrSchedule([email protected]/SequentialScheduler.Java:271)
        at jdk.internal.net.http.common.SequentialScheduler.runOrSchedule([email protected]/SequentialScheduler.Java:224)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer.triggerWrite([email protected]/SSLFlowDelegate.Java:722)
        at jdk.internal.net.http.common.SSLFlowDelegate.doHandshake([email protected]/SSLFlowDelegate.Java:1024)
        at jdk.internal.net.http.common.SSLFlowDelegate.doClosure([email protected]/SSLFlowDelegate.Java:1094)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader.unwrapBuffer([email protected]/SSLFlowDelegate.Java:500)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData([email protected]/SSLFlowDelegate.Java:389)
        - locked <0x00000000f97668d0> (a Java.lang.Object)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreamPusher.run([email protected]/SSLFlowDelegate.Java:263)
        at jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run([email protected]/SequentialScheduler.Java:175)
        - locked <0x00000000f97668f0> (a Java.lang.Object)
        at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run([email protected]/SequentialScheduler.Java:147)
        at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run([email protected]/SequentialScheduler.Java:198)
        at Java.util.concurrent.ThreadPoolExecutor.runWorker([email protected]/ThreadPoolExecutor.Java:1128)
        at Java.util.concurrent.ThreadPoolExecutor$Worker.run([email protected]/ThreadPoolExecutor.Java:628)
        at Java.lang.Thread.run([email protected]/Thread.Java:834)

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

同じ観察ですが、影響を受けたスレッドが1つだけの別のコンテナーで。

"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([email protected]/SSLEngineImpl.Java:136)
        - eliminated <0x00000000f9796e08> (a Sun.security.ssl.SSLEngineImpl)
        at Sun.security.ssl.SSLEngineImpl.wrap([email protected]/SSLEngineImpl.Java:116)
        - locked <0x00000000f9796e08> (a Sun.security.ssl.SSLEngineImpl)
        at javax.net.ssl.SSLEngine.wrap([email protected]/SSLEngine.Java:519)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer.wrapBuffers([email protected]/SSLFlowDelegate.Java:821)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer.processData([email protected]/SSLFlowDelegate.Java:736)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer$WriterDownstreamPusher.run([email protected]/SSLFlowDelegate.Java:645)
        at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run([email protected]/SequentialScheduler.Java:147)
        at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run([email protected]/SequentialScheduler.Java:198)
        at jdk.internal.net.http.common.SequentialScheduler.runOrSchedule([email protected]/SequentialScheduler.Java:271)
        at jdk.internal.net.http.common.SequentialScheduler.runOrSchedule([email protected]/SequentialScheduler.Java:224)
        at jdk.internal.net.http.common.SSLFlowDelegate$Writer.triggerWrite([email protected]/SSLFlowDelegate.Java:722)
        at jdk.internal.net.http.common.SSLFlowDelegate.doHandshake([email protected]/SSLFlowDelegate.Java:1024)
        at jdk.internal.net.http.common.SSLFlowDelegate.doClosure([email protected]/SSLFlowDelegate.Java:1094)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader.unwrapBuffer([email protected]/SSLFlowDelegate.Java:500)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData([email protected]/SSLFlowDelegate.Java:389)
        - locked <0x00000000f9797010> (a Java.lang.Object)
        at jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreamPusher.run([email protected]/SSLFlowDelegate.Java:263)
        at jdk.internal.net.http.common.SequentialScheduler$SynchronizedRestartableTask.run([email protected]/SequentialScheduler.Java:175)
        - locked <0x00000000f9797030> (a Java.lang.Object)
        at jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run([email protected]/SequentialScheduler.Java:147)
        at jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run([email protected]/SequentialScheduler.Java:198)
        at Java.util.concurrent.ThreadPoolExecutor.runWorker([email protected]/ThreadPoolExecutor.Java:1128)
        at Java.util.concurrent.ThreadPoolExecutor$Worker.run([email protected]/ThreadPoolExecutor.Java:628)
        at Java.lang.Thread.run([email protected]/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に固定できます(nginx docker image:nginx:1.15-Alpineを使用して、もちろんtls1.3を有効にします)
17
Zarathustra

@jspcalが前に言ったように、TLS 1.3を無効にします。

tl; dr:拡張/上書きによってtlsv1.3を無効にします

<Java_home>/conf/security/Java.securityjdk.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も参照してください。

更新:11.0.2にはまだバグがあります

6
Zarathustra

TLSv1.3またはSSLv3を無効にして、効果があるかどうかを確認してください。

コマンドラインでシステムプロパティを設定します:-Djdk.tls.disabledAlgorithms=TLSv1.3

または、<Java_home>/conf/security/Java.securityでプロパティを定義します

実装のバグだと思われる場合は、問題をオープンすることをお勧めします。

6
jspcal