11# Production-Ready Accept Loop
22
3- Production -ready accept loop needs the following things:
3+ A production -ready accept loop needs the following things:
441 . Handling errors
552 . Limiting the number of simultanteous connections to avoid deny-of-service
66 (DoS) attacks
77
88
99## Handling errors
1010
11- There are two kinds of errors in accept loop:
12- 1 . Per-connection errors. System uses them to notify that there was a
13- connection in the queue and it's dropped by peer. Subsequent connection
11+ There are two kinds of errors in an accept loop:
12+ 1 . Per-connection errors. The system uses them to notify that there was a
13+ connection in the queue and it's dropped by the peer. Subsequent connections
1414 can be already queued so next connection must be accepted immediately.
15152 . Resource shortages. When these are encountered it doesn't make sense to
16- accept next socket immediately. But listener stays active, so you server
16+ accept the next socket immediately. But the listener stays active, so you server
1717 should try to accept socket later.
1818
19- Here is the example of per-connection error (printed in normal and debug mode):
19+ Here is the example of a per-connection error (printed in normal and debug mode):
2020```
2121Error: Connection reset by peer (os error 104)
2222Error: Os { code: 104, kind: ConnectionReset, message: "Connection reset by peer" }
@@ -30,10 +30,10 @@ Error: Os { code: 24, kind: Other, message: "Too many open files" }
3030
3131### Testing Application
3232
33- To test your application on these errors try the following (this works
33+ To test your application for these errors try the following (this works
3434on unixes only).
3535
36- Lower limit and start the application:
36+ Lower limits and start the application:
3737```
3838$ ulimit -n 100
3939$ cargo run --example your_app
@@ -42,7 +42,7 @@ $ cargo run --example your_app
4242 Running `target/debug/examples/your_app`
4343Server is listening on: http://127.0.0.1:1234
4444```
45- Then in another console run [ ` wrk ` ] benchmark tool:
45+ Then in another console run the [ ` wrk ` ] benchmark tool:
4646```
4747$ wrk -c 1000 http://127.0.0.1:1234
4848Running 10s test @ http://localhost:8080/
@@ -54,26 +54,26 @@ Connected to localhost.
5454
5555Important is to check the following things:
5656
57- 1 . Application doesn't crash on error (but may log errors, see below)
57+ 1 . The application doesn't crash on error (but may log errors, see below)
58582 . It's possible to connect to the application again once load is stopped
5959 (few seconds after ` wrk ` ). This is what ` telnet ` does in example above,
6060 make sure it prints ` Connected to <hostname> ` .
61613 . The ` Too many open files ` error is logged in the appropriate log. This
6262 requires to set "maximum number of simultaneous connections" parameter (see
63- below) of your application to a value greater that ` 100 ` for this example.
63+ below) of your application to a value greater then ` 100 ` for this example.
64644 . Check CPU usage of the app while doing a test. It should not occupy 100%
6565 of a single CPU core (it's unlikely that you can exhaust CPU by 1000
6666 connections in Rust, so this means error handling is not right).
6767
6868#### Testing non-HTTP applications
6969
7070If it's possible, use the appropriate benchmark tool and set the appropriate
71- number of connections. For example ` redis-benchmark ` has ` -c ` parameter for
71+ number of connections. For example ` redis-benchmark ` has a ` -c ` parameter for
7272that, if you implement redis protocol.
7373
7474Alternatively, can still use ` wrk ` , just make sure that connection is not
7575immediately closed. If it is, put a temporary timeout before handing
76- connection to the protocol handler, like this:
76+ the connection to the protocol handler, like this:
7777
7878``` rust,edition2018
7979# extern crate async_std;
@@ -147,7 +147,7 @@ Be sure to [test your application](#testing-application).
147147
148148### External Crates
149149
150- The crate [ ` async-listen ` ] have a helper to achieve this task:
150+ The crate [ ` async-listen ` ] has a helper to achieve this task:
151151``` rust,edition2018
152152# extern crate async_std;
153153# extern crate async_listen;
@@ -200,7 +200,7 @@ Even if you've applied everything described in
200200Let's imagine you have a server that needs to open a file to process
201201client request. At some point, you might encounter the following situation:
202202
203- 1 . There are as much client connection as max file descriptors allowed for
203+ 1 . There are as many client connection as max file descriptors allowed for
204204 the application.
2052052 . Listener gets ` Too many open files ` error so it sleeps.
2062063 . Some client sends a request via the previously open connection.
@@ -257,7 +257,7 @@ async fn connection_loop(_token: &Token, stream: TcpStream) { // 4
257257 stream of ` TcpStream ` rather than ` Result ` .
2582582 . The token yielded by a new stream is what is counted by backpressure helper.
259259 I.e. if you drop a token, new connection can be established.
260- 3 . We give connection loop a reference to token to bind token's lifetime to
260+ 3 . We give the connection loop a reference to token to bind token's lifetime to
261261 the lifetime of the connection.
2622624 . The token itsellf in the function can be ignored, hence ` _token `
263263
0 commit comments