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

async executor on nginx event loop #110

Open
bavshin-f5 opened this issue Dec 24, 2024 · 0 comments
Open

async executor on nginx event loop #110

bavshin-f5 opened this issue Dec 24, 2024 · 0 comments

Comments

@bavshin-f5
Copy link
Collaborator

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.

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

No branches or pull requests

1 participant