-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[HttpClient] Allow setting max persistent connections in CurlHttpClient
#58270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
SERVER_NAME: 'http://localhost' | ||
SERVER_NAME: 'http://localhost http://localhost:81 http://localhost:82' | ||
CADDY_SERVER_EXTRA_DIRECTIVES: | | ||
route /http-client* { | ||
root * /symfony/src/Symfony/Component/HttpClient/Tests/Fixtures/response-functional/ | ||
php_server | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PHP built-in server doesn't support persistent connections.
@@ -45,6 +45,7 @@ final class CurlHttpClient implements HttpClientInterface, LoggerAwareInterface, | |||
// password as the second one; or string like username:password - enabling NTLM auth | |||
'extra' => [ | |||
'curl' => [], // A list of extra curl options indexed by their corresponding CURLOPT_* | |||
'max_connections' => null, // The maximum amount of simultaneously open connections, corresponds to CURLMOPT_MAXCONNECTS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't put it under curl
as this is a curl multi-handler option.
if (\defined('CURLMOPT_MAXCONNECTS') && 0 < $maxHostConnections) { | ||
curl_multi_setopt($this->handle, \CURLMOPT_MAXCONNECTS, $maxHostConnections); | ||
if (\defined('CURLMOPT_MAXCONNECTS') && null !== $maxConnections ??= 0 < $maxHostConnections ? $maxHostConnections : null) { | ||
curl_multi_setopt($this->handle, \CURLMOPT_MAXCONNECTS, $maxConnections); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of adding a new option, can you try removing this line and see if curl doesn't do better by default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I re-read your description, you tell about it already.
Then what about setting $maxHostConnections
to 500?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nicolas-grekas Unfortunately, setting $maxHostConnections
only sets CURLMOPT_MAX_HOST_CONNECTIONS
. This doesn't change CURLMOPT_MAXCONNECTS
which by default is 4 times the number of added handlers. I've already tried this, and it didn't work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about making this a constructor argument with a corresponding configuration option in framework-bundle?
This would require implementing the limiting for Amp too.
Up to have a look?
@nicolas-grekas I'll se what I can do. I thought about that initially and played a bit with the |
@@ -52,8 +52,8 @@ public function __construct(int $maxHostConnections, int $maxPendingPushes) | |||
if (\defined('CURLMOPT_MAX_HOST_CONNECTIONS')) { | |||
$maxHostConnections = curl_multi_setopt($this->handle, \CURLMOPT_MAX_HOST_CONNECTIONS, 0 < $maxHostConnections ? $maxHostConnections : \PHP_INT_MAX) ? 0 : $maxHostConnections; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think 0
is the issue. It's not documented as meaning "infinite", unlike many other curl options.
$maxHostConnections = curl_multi_setopt($this->handle, \CURLMOPT_MAX_HOST_CONNECTIONS, 0 < $maxHostConnections ? $maxHostConnections : \PHP_INT_MAX) ? 0 : $maxHostConnections; | |
$maxHostConnections = curl_multi_setopt($this->handle, \CURLMOPT_MAX_HOST_CONNECTIONS, 0 < $maxHostConnections ? $maxHostConnections : \PHP_INT_MAX) ? \PHP_INT_MAX : $maxHostConnections; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nicolas-grekas Yes, you're right, see #58278. I opened it as a bug fix, if it's not, please let me know.
Closing in favor of #58278 |
This PR was merged into the 5.4 branch. Discussion ---------- [HttpClient] Fix setting `CURLMOPT_MAXCONNECTS` | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | - | License | MIT An alternative approach for #58270, see #58270 (comment). Commits ------- 4f9b5de [HttpClient] Fix setting CURLMOPT_MAXCONNECTS
Currently, it's not possible to set the maximum number of simultaneously open connections in the
CurlHttpClient
. ThemaxHostConnections
option potentially setsCURLMOPT_MAXCONNECTS
, but only ifCURLMOPT_MAX_HOST_CONNECTIONS
isn't defined:symfony/src/Symfony/Component/HttpClient/Internal/CurlClientState.php
Lines 52 to 57 in d575fa5
This, of course, isn't helpful if you want
CURLMOPT_MAXCONNECTS
to always be set.In my use case, I have workers that processes queued URLs and sends purge requests to our multiple Varnish servers. The workers are long-running processes that processes the queue one item at a time, as each request must be handled in real time, making it impossible to delay or batch the URLs. This means that the number of simultaneously open cURL handlers per worker is usually just one. Given that the default configuration for
CURLMOPT_MAXCONNECTS
is 4 times the number of added handlers, this configuration is insufficient, as we have more than 4 Varnish servers. As a result, connections are constantly being opened and closed by each worker. Keeping these connections persistently open significantly reduces the time required to make each request.I've tested the performance using the following hack:
Here are some graphs that show the results (the dotted vertical line represents the time of deployment):
The first graph shows the number of new connections being established by the workers. As you can see, it dropped to almost zero.
The second graph shows the time it takes to perform the requests. After the initial persistent connections are established, the time significantly decreases.
Even though this hack works, being able to configure this through an option would be much better.