cURL 在一些失败的请求后随机抛出“curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL”

Fog*_*gus 6 php curl apple-push-notifications

我有一个 PHP 脚本,可以快速向 Apple API ( APNs )发送一堆请求。有时 10k 请求发送完全没问题(只是为了记录,大约需要 30 秒)。但是,当 API 返回一些非 200 代码时,与此 API 建立新连接会引发以下错误:

curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to api.push.apple.com:443
Run Code Online (Sandbox Code Playgroud)

启用调试模式后,我得到了奇怪的结果:

当一切正常时:

* Found bundle for host api.push.apple.com: 0x55eba8b11660 [serially]
* Found bundle for host api.push.apple.com: 0x55eba8b11660 [serially]
*   Trying 17.188.140.151...
* TCP_NODELAY set
* Hostname 'api.push.apple.com' was found in DNS cache
*   Trying 17.188.140.151...
...
...
Run Code Online (Sandbox Code Playgroud)

(完整输出在这里)。

问题发生后:

* Found bundle for host api.push.apple.com: 0x561d83bb1f00 [serially]
* Server doesn't support multiplex (yet)
* Connection #0 is still name resolving, can't reuse
* Found bundle for host api.push.apple.com: 0x561d83bb1f00 [serially]
* Server doesn't support multiplex (yet)
* Connection #0 is still name resolving, can't reuse
* Connection #1 is still name resolving, can't reuse
*   Trying 17.188.156.30:443...
* TCP_NODELAY set
* Hostname 'api.push.apple.com' was found in DNS cache
*   Trying 17.188.156.30:443...
...
...
Run Code Online (Sandbox Code Playgroud)

(完整输出在这里)。

因此,IP 已更改,并且与多路复用有关。

发生这种情况后,使用 cli 向此 API 发送请求curl也会停止工作:

$ curl -v -I https://api.push.apple.com
*   Trying 17.188.156.30:443...
* TCP_NODELAY set
* Connected to api.push.apple.com (17.188.156.30) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to api.push.apple.com:443 
* Closing connection 0
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to api.push.apple.com:443 
Run Code Online (Sandbox Code Playgroud)

(完整输出在这里)。

该错误可能会在几分钟后消失,也可能不会。代码在 docker 容器 (php:7.3-cli-alpine) 中运行,重新启动容器通常会重置问题,直到将来的某些请求获得非 200 代码。执行重新启动不是一种选择。

据推测,curl 以某种方式存储打开的连接并尝试重新使用它们,但由于某种原因,curl 内部有些东西被破坏了,它不允许 curl 正确地重新使用这些连接。

当 curl 停止工作时,openssl 工作正常:

$ openssl s_client -connect api.push.apple.com:443
CONNECTED(00000003)
write:errno=0
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 320 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
Run Code Online (Sandbox Code Playgroud)

软件版本:

$ curl --version
curl 7.67.0 (x86_64-alpine-linux-musl) libcurl/7.67.0 OpenSSL/1.1.1d zlib/1.2.11 nghttp2/1.40.0
Release-Date: 2019-11-06
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS HTTP2 HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL TLS-SRP UnixSockets

$ openssl version
OpenSSL 1.1.1d  10 Sep 2019
Run Code Online (Sandbox Code Playgroud)

看起来像是卷曲问题,但如何解决?

任何帮助将不胜感激

小智 4

以防万一它对您或其他人有帮助,“一个错误会长时间破坏事情”的本质(以及 Curl 连接的重用)让我想起了一些 Curl bug: https://github。 com/curl/curl/issues/3966

不确定你的 Curl 版本中是否有此修复 - 从可能的日期开始。

  • 嗨@josie-h,欢迎来到 Stack Overflow :) 我看到你正在尝试提供一些可能对 OP 或一般人有帮助的信息,但它实际上并不是问题的答案。当您获得足够的声誉时,您可以提供诸如对问题的评论之类的输入,而不是答案......:) (2认同)