Support HTTP keep-alive for HTTP client (reusing persistent connections) #486
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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:
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 theConnection
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)