mirror of
https://github.com/actix/actix-website
synced 2024-11-27 18:12:57 +01:00
Add explanations regarding actix-web's multithreaded server model (#150)
* Add explanations regarding actix-web's multithreaded server model * Improve phrasing * Typo fix Co-authored-by: Yuki Okushi <huyuumi.dev@gmail.com>
This commit is contained in:
parent
c1a8103cbc
commit
8c8de9f7fb
@ -31,18 +31,53 @@ Following example shows how to start http server in separate thread.
|
|||||||
|
|
||||||
## Multi-threading
|
## Multi-threading
|
||||||
|
|
||||||
`HttpServer` automatically starts a number of http workers, by default this number is
|
`HttpServer` automatically starts a number of http *workers*, by default this number is
|
||||||
equal to number of logical CPUs in the system. This number can be overridden with the
|
equal to number of logical CPUs in the system. This number can be overridden with the
|
||||||
[`HttpServer::workers()`][workers] method.
|
[`HttpServer::workers()`][workers] method.
|
||||||
|
|
||||||
{{< include-example example="server" file="workers.rs" section="workers" >}}
|
{{< include-example example="server" file="workers.rs" section="workers" >}}
|
||||||
|
|
||||||
The server creates a separate application instance for each created worker. Application state
|
Once the workers are created, they each receive a separate *application* instance to handle
|
||||||
is not shared between threads. To share state, `Arc` could be used.
|
requests. Application state is not shared between the threads, and handlers are free to manipulate
|
||||||
|
their copy of the state with no concurrency concerns.
|
||||||
|
|
||||||
> Application state does not need to be `Send` or `Sync`, but application
|
> Application state does not need to be `Send` or `Sync`, but application
|
||||||
factory must be `Send` + `Sync`.
|
factory must be `Send` + `Sync`.
|
||||||
|
|
||||||
|
To share state between worker threads, use an `Arc`. Special care should be taken once sharing and
|
||||||
|
synchronization are introduced. In many cases, performance costs are inadvertently introduced as a
|
||||||
|
result of locking the shared state for modifications.
|
||||||
|
|
||||||
|
In some cases these costs can be alleviated using more efficient locking strategies, for example
|
||||||
|
using [read/write locks](https://doc.rust-lang.org/std/sync/struct.RwLock.html) instead of
|
||||||
|
[mutexes](https://doc.rust-lang.org/std/sync/struct.Mutex.html) to achieve non-exclusive locking,
|
||||||
|
but the most performant implementations often tend to be ones in which no locking occurs at all.
|
||||||
|
|
||||||
|
Since each worker thread processes its requests sequentially, handlers which block the current
|
||||||
|
thread will cause the current worker to stop processing new requests:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn my_handler() -> impl Responder {
|
||||||
|
std::thread::sleep(Duration::from_secs(5)); // <-- Bad practice! Will cause the current worker thread to hang!
|
||||||
|
"response"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
For this reason, any long, non-cpu-bound operation (e.g. I/O, database operations, etc.) should be
|
||||||
|
expressed as futures or asynchronous functions. Async handlers get executed concurrently by worker
|
||||||
|
threads and thus don't block execution:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
async fn my_handler() -> impl Responder {
|
||||||
|
tokio::time::delay_for(Duration::from_secs(5)).await; // <-- Ok. Worker thread will handle other requests here
|
||||||
|
"response"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The same limitation applies to extractors as well. When a handler function receives an argument
|
||||||
|
which implements `FromRequest`, and that implementation blocks the current thread, the worker thread
|
||||||
|
will block when running the handler. Special attention must be given when implementing extractors
|
||||||
|
for this very reason, and they should also be implemented asynchronously where needed.
|
||||||
|
|
||||||
## SSL
|
## SSL
|
||||||
|
|
||||||
There are two features for the ssl server: `rustls` and `openssl`. The `rustls` feature is for
|
There are two features for the ssl server: `rustls` and `openssl`. The `rustls` feature is for
|
||||||
|
Loading…
Reference in New Issue
Block a user