Как повторно использовать соединения с curl_easy? - PullRequest
3 голосов
/ 14 июля 2020

Я пишу код с curl_easy интерфейсом libcurl, и мне трудно заставить его повторно использовать соединения. Подробности ниже.

curl --version
curl 7.58.0 (x86_64-pc-linux-gnu) libcurl/7.58.0 OpenSSL/1.1.1 zlib/1.2.11
libidn2/2.0.4 libpsl/0.19.1 (+libidn2/2.0.4) nghttp2/1.30.0 librtmp/2.3
Release-Date: 2018-01-24
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3
pop3s rtmp rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB
SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL

Мой код проходит через серию модульных тестов, каждый из которых должен подключаться к одному и тому же хосту через H2, поэтому я установил постоянные соединения. Я вызываю curl_easy_init один раз, затем все глобальные curl_easy_setopt значения, затем в l oop, я делаю запросы, вызывая curl_easy_setopt, чтобы установить поля сообщения, URL-адрес, длину содержимого, а затем curl_easy_perform. Я звоню curl_easy_cleanup только после того, как будут сделаны все запросы. У меня установлены следующие параметры:

CURLOPT_FOLLOWLOCATION => 1
CURLOPT_SSL_VERIFYPEER => 1
CURLOPT_SSL_VERIFYHOST => 2
CURLOPT_SSLVERSION 7<<16
CURLOPT_HTTP_VERSION = 4
CURLOPT_TCP_FASTOPEN = 1
CURLOPT_TCP_KEEPALIVE = 1
CURLOPT_ACCEPT_ENCODING = ""
CURLOPT_TRANSFER_ENCODING = 1
CURLOPT_POST = 1
CURLOPT_DNS_CACHE_TIMEOUT = 0
CURLOPT_VERBOSE = 1
CURLOPT_SSLCERT
CURLOPT_SSLKEY
CURLOPT_CAINFO

Подробный вывод выглядит так:

* TCP_NODELAY set
* TCP_FASTOPEN_CONNECT set
* Connected to XYZ () port 443 (#0)
* found 3 certificates in /data/certs/ca_chain.pem
* found 401 certificates in /etc/ssl/certs
* ALPN, offering h2
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
* server certificate verification OK
* server certificate status verification SKIPPED
* error fetching CN from cert:The requested data were not available.
* common name: (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject:
* start date: Mon, 13 Jul 2020 08:04:30 GMT
* expire date: Mon, 20 Jul 2020 08:05:00 GMT
* issuer: C=US,ST=MA,L=Cambridge,O=XXXXX,CN=YYYYY
* compression: NULL
* ALPN, server accepted to use h2
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade:
len=0
* Using Stream ID: 1 (easy handle 0x9036570)
> POST /foo/ HTTP/2

<Request>

* We are completely uploaded and fine
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!

<Response>

* Connection #0 to host XYZ left intact
* Found bundle for host XYZ: 0xe141520 [can multiplex]
* Connection #0 is still name resolving, can't reuse
* Trying IP...
* TCP_NODELAY set
* TCP_FASTOPEN_CONNECT set
* Connected to XYZ () port 443 (#1)
* found 3 certificates in /data/certs/ca_chain.pem
* found 401 certificates in /etc/ssl/certs
* ALPN, offering h2
* ALPN, offering http/1.1
* SSL re-using session ID
* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
* server certificate verification OK
* server certificate status verification SKIPPED
* error fetching CN from cert:The requested data were not available.
* common name: (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject:
* start date: Mon, 13 Jul 2020 08:04:30 GMT
* expire date: Mon, 20 Jul 2020 08:05:00 GMT
* issuer: C=US,ST=MA,L=Cambridge,O=XXXXX,CN=YYYYY
* compression: NULL
* ALPN, server accepted to use h2
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade:
len=0
* Using Stream ID: 1 (easy handle 0x9036570)

<Request>

* We are completely uploaded and fine
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
< vary: accept-encoding
< content-encoding: gzip
< content-type: text/plain
< date: Mon, 13 Jul 2020 19:30:36 GMT
< server: abcdefg

<Response>

* Connection #1 to host XYZ left intact
* Found bundle for host XYZ: 0xe141520 [can multiplex]
* Connection #0 is still name resolving, can't reuse
* Connection #1 is still name resolving, can't reuse

И так далее ...

Это довольно скоро доходит до этого:

* Connection cache is full, closing the oldest one.
* Closing connection 0
* Connection #5 to host XYZ left intact

Это закрытие самого старого соединения продолжается с этого момента до тех пор, пока либо все не будет сделано, либо ошибка установления связи TLS переведет соединение в несогласованное состояние.

Есть идеи, что я могу сделать, чтобы заставить curl повторно использовать соединение H2 с хостом?

Спасибо за ваше время.

1 Ответ

0 голосов
/ 14 июля 2020

Проблема связана с CURLOPT_TCP_FASTOPEN. Отключение этой опции позволит повторно использовать соединение. FAST_OPEN требуется только при использовании нескольких TCP-соединений, чтобы избежать обхода во время рукопожатия.

...