`async` executor on nginx event loop
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 915
- Forks
- 96
- Avg merge
- 5d 22h
- Merged PRs (30d)
- 6
Description
Previously, we had evaluated use of tokio within the modules. The results weren't reassuring:
nginx is optimized to be a multi-process single-threaded application. None of the internal APIs are thread safe, and it's extremely dangerous to call some methods from another thread (anything that deals with IO scheduling, timers or other globals). Rare cases of thread interaction (thread pools in aio threads) are not cross-platform and have bottlenecks. Additionally, the notification method from the thread pools (ngx_notify) is a private detail, not reusable without changing the API.
- Any data sent to the tokio runtime should be fully copied and detached from the nginx internal structures (
ngx_http_request_t). That is expensive. - Any events, including incoming body, generated response bytes, abnormal termination of the request, etc, must be passed between threads through a synchronized event queue. Said event queue should integrate with the nginx main loop using platform-dependent methods (
eventfd,kevent, etc) or risk degrading performance even more. - Thread synchronization may cause delayed or blocking reaction on the nginx events. E.g. task cancellation when the request is aborted and the cleanup handler is running, must be synchronous.
- Threads mess up CPU affinities, data locality, etc. That adds to the already non-negligible costs of copying the data.
Ideally, we want to have everything in the main thread of a worker process, unless it's a blocking task that should be offloaded to the thread pool.
Considering all of the above, it appears to be safer and simpler for us to implement our own task executor running on top of the nginx event loop. The Rust ecosystem offers enough components and examples for that.
The MVP goal for this task is to be able to run hyper/client as an upstream implementation; that is a sufficiently complex use case for an async runtime.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the nginx event loop and the existing aio threads/ngx_notify interaction described in the issue, then assess how hyper/client can run without crossing ngx_http_request_t thread-safety boundaries. Define the executor and event-queue behavior for request bodies, response bytes, abort cleanup, and cancellation; done means the MVP runs hyper/client on the nginx event loop.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nginx, rust
- Domain
- backend, networking
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 28/100