Skip to content
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

Support HTTP keep-alive for HTTP client (reusing persistent connections) #486

Merged
merged 4 commits into from
Jan 24, 2023

Conversation

clue
Copy link
Member

@clue clue commented Jan 20, 2023

This changeset adds optional support for HTTP keep-alive for the HTTP client (reusing persistent connections). This offers significant performance improvements when sending many requests to the same host as it avoids recreating the underlying TCP/IP connection and repeating the TLS handshake for secure HTTPS requests.

This improvement is especially noticeable when queuing many requests to the same host as discussed in https://github.com/reactphp/http#concurrency or following HTTP redirects on the same host. Depending on your network speed to the host, this may show anywhere from a few percent to 300% faster responses, but you're invited to run your own benchmarks and share your results!

HTTP keep-alive is currently disabled by default to not affect existing deployments and can easily be enabled like this:

$browser = new React\Http\Browser();

// remove default `Connection: close` request header to enable HTTP keep-alive
$browser = $browser->withoutHeader('Connection');

$response = React\Async\await($browser->get('https://httpbingo.org/redirect/6'));
assert($response instanceof Psr\Http\Message\ResponseInterface);

There are future plans to enable HTTP keep-alive by default, but I'd like to get some feedback on this feature first before enabling this in a future version. Additionally, idle connections will currently only be kept alive for a maximum of 1ms between requests to make sure consumers of this library will not be affected negatively. By using a very short timeout period, the loop does not keep running noticeably longer than without this feature. This doesn't matter for long running scripts, but it's important for short running scripts to not appear to be "blocked". In the future, we should give more control over this timeout to allow reusing connections also for common use cases of periodically polling hosts using a longer interval. On top of this, we may want to introduce functions to explicitly soft-close and/or hard-close (idle) connections.

Applying these changes required a significant refactoring of the existing logic first. This does not otherwise affect the public React\Http\Browser class or any other public APIs, so this should be safe to apply. In particular, this changeset should not affect existing behavior if you do not change the Connection request header. The test suite confirms this has 100% code coverage and does not otherwise affect our public APIs.

Together with the preparations for this feature in #484, #482, #481, #480 and others you're looking at several weeks(!) of work, so I think this might be one of the largest feature additions in ReactPHP lately, enjoy! Special thanks to our sponsors for making this possible! If you'd like to support this development, consider sponsoring ReactPHP! ❤️

Builds on top of #484, #482, #481, #480 and others
Resolves #468 (HTTP keep-alive)
Also refs #376 (future support for HTTP upgrades)

src/Io/ClientConnectionManager.php Show resolved Hide resolved
src/Io/ClientConnectionManager.php Outdated Show resolved Hide resolved
src/Io/ClientConnectionManager.php Outdated Show resolved Hide resolved
@SimonFrings SimonFrings merged commit a221964 into reactphp:1.x Jan 24, 2023
@SimonFrings SimonFrings deleted the keep-alive branch January 24, 2023 11:58
@sashaaro
Copy link

sashaaro commented Feb 1, 2023

Nice feature

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HTTP client: Support persistent connections (aka HTTP/1.1 Keep-Alive)
4 participants