From 0556fb027c44cf80d3f77fb9c3fac4c504d6720c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Sun, 23 Jul 2017 09:48:25 +0200 Subject: [PATCH] Update the flowchart chapter --- doc/src/guide/book.asciidoc | 10 - doc/src/guide/flow_diagram.asciidoc | 49 ++- doc/src/guide/http_req_resp.png | Bin 28370 -> 20713 bytes doc/src/guide/http_req_resp.svg | 557 +++++++++++++++------------- doc/src/guide/overview.asciidoc | 150 -------- 5 files changed, 337 insertions(+), 429 deletions(-) delete mode 100644 doc/src/guide/overview.asciidoc diff --git a/doc/src/guide/book.asciidoc b/doc/src/guide/book.asciidoc index 81788032..ed0f1c73 100644 --- a/doc/src/guide/book.asciidoc +++ b/doc/src/guide/book.asciidoc @@ -80,13 +80,3 @@ include::migrating_from_1.0.asciidoc[Migrating from Cowboy 1.0 to 2.0] // @todo Maybe history? Could take info from architecture also. include::specs.asciidoc[HTTP and other specifications] - -= Deprecated chapters - -== About the deprecated chapters - -The following chapters were relevant in Cowboy 1.0. They have -not been updated for Cowboy 2.0 yet. The information in these -chapters may or may not be useful. - -include::overview.asciidoc[Overview] diff --git a/doc/src/guide/flow_diagram.asciidoc b/doc/src/guide/flow_diagram.asciidoc index 4cb3bda2..2d35d4d6 100644 --- a/doc/src/guide/flow_diagram.asciidoc +++ b/doc/src/guide/flow_diagram.asciidoc @@ -9,9 +9,54 @@ information about how the network connections are handled. === Overview -Placeholder section. +image::http_req_resp.png[HTTP request/response flowchart] -// @todo Make the diagram. +As you can see on the diagram, the client +begins by connecting to the server. This step is handled +by a Ranch acceptor, which is a process dedicated to +accepting new connections. + +After Ranch accepts a new connection, whether it is an +HTTP/1.1 or HTTP/2 connection, Cowboy starts receiving +requests and handling them. + +In HTTP/1.1 all requests come sequentially. In HTTP/2 +the requests may arrive and be processed concurrently. + +When a request comes in, Cowboy creates a stream, which +is a set of request/response and all the events associated +with them. The protocol code in Cowboy defers the handling +of these streams to stream handler modules. When you +configure Cowboy you may define one or more module that +will receive all events associated with a stream, including +the request, response, bodies, Erlang messages and more. + +By default Cowboy comes configured with a stream handler +called `cowboy_stream_h`. This stream handler will create +a new process for every request coming in, and then +communicate with this process to read the body or send +a response back. The request process executes middlewares +which, by default, including the router and then the +execution of handlers. Like stream handlers, middlewares +may also be customized. + +A response may be sent at almost any point in this +diagram. If the response must be sent before the stream +is initialized (because an error occurred early, for +example) then stream handlers receive a special event +indicating this error. + +=== Protocol-specific headers + +Cowboy takes care of protocol-specific headers and prevents +you from sending them manually. For HTTP/1.1 this includes +the `transfer-encoding` and `connection` headers. For HTTP/2 +this includes the colon headers like `:status`. + +Cowboy will also remove protocol-specific headers from +requests before passing them to stream handlers. Cowboy +tries to hide the implementation details of all protocols +as well as possible. === Number of processes per connection diff --git a/doc/src/guide/http_req_resp.png b/doc/src/guide/http_req_resp.png index 8c9cae9948161951df06513229b0763609fdd403..41c17c8a55396a54b15033edc627f3c87d07ded8 100644 GIT binary patch literal 20713 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 h_tWeN^3QEBpT8m;M @@ -101,51 +101,117 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1"> - - - - + + + + + + + + + + + + + + + + - - - - - - some text - acceptor - some text + + + + acceptor + + + + + protocol + + + + parser + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;-inkscape-font-specification:Sans;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#77823c;fill-opacity:1;stroke:none" + xml:space="preserve">router + router - some text - some text + + + handler + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;-inkscape-font-specification:Sans;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#6d8e41;fill-opacity:1;stroke:none" + xml:space="preserve">handler + middlewares + x="-470.30792" + y="63.078125" + style="font-size:16px;line-height:1.25;font-family:sans-serif">middlewares some text - some text + + + client - - - - - reply - onresponse + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;-inkscape-font-specification:Sans;text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#9b3b1c;fill-opacity:1;stroke:none" + xml:space="preserve">client + + + + stream + diff --git a/doc/src/guide/overview.asciidoc b/doc/src/guide/overview.asciidoc deleted file mode 100644 index 3e5cbb74..00000000 --- a/doc/src/guide/overview.asciidoc +++ /dev/null @@ -1,150 +0,0 @@ -[[overview]] -== Request overview - -This chapter explains the different steps a request -goes through until a response is sent, along with -details of the Cowboy implementation. - -=== Request/response - -As you already know, HTTP clients connect to the server and -send a request for a resource; the server then sends a -response containing the resource if it could obtain it. - -Before the server can send the resource, however, it -needs to perform many different operations to read the -request, find the resource, prepare the response being -sent and often other related operations the user can -add like writing logs. - -Requests take the following route in Cowboy: - -image::http_req_resp.png[HTTP request/response flowchart] - -This shows the default middlewares, but they may be -configured differently in your setup. The dark green -indicates the points where you can hook your own code, -the light green is the Cowboy code that you can of -course configure as needed. - -The `acceptor` is the part of the server that accepts -the connection and create an Erlang process to handle -it. The `parser` then starts reading from the socket -and handling requests as they come until the socket -is closed. - -A response may be sent at many different points in the -life of the request. If Cowboy can't parse the request, -it gives up with an error response. If the router can't -find the resource, it sends a not found error. Your -own code can of course send a response at any time. - -When a response is sent, you can optionally modify it -or act upon it by enabling the `onresponse` hook. By -default the response is sent directly to the client. - -=== And then? - -Behavior depends on what protocol is in use. - -HTTP/1.0 can only process one request per connection, -so Cowboy will close the connection immediately after -it sends the response. - -HTTP/1.1 allows the client to request that the server -keeps the connection alive. This mechanism is described -in the next section. - -HTTP/2 is designed to allow sending multiple requests -asynchronously on the same connection. Details on what -this means for your application is described in this -chapter. - -=== Keep-alive (HTTP/1.1) - -With HTTP/1.1, the connection may be left open for -subsequent requests to come. This mechanism is called -`keep-alive`. - -When the client sends a request to the server, it includes -a header indicating whether it would like to leave the -socket open. The server may or may not accept, indicating -its choice by sending the same header in the response. - -Cowboy will include this header automatically in all -responses to HTTP/1.1 requests. You can however force -the closing of the socket if you want. When Cowboy sees -you want to send a `connection: close` header, it will -not override it and will close the connection as soon -as the reply is sent. - -This snippet will force Cowboy to close the connection. - -[source,erlang] ----- -Req2 = cowboy_req:reply(200, [ - {<<"connection">>, <<"close">>}, -], <<"Closing the socket in 3.. 2.. 1..">>, Req). ----- - -Cowboy will only accept a certain number of new requests -on the same connection. By default it will run up to 100 -requests. This number can be changed by setting the -`max_keepalive` configuration value when starting an -HTTP listener. - -[source,erlang] ----- -cowboy:start_http(my_http_listener, 100, [{port, 8080}], [ - {env, [{dispatch, Dispatch}]}, - {max_keepalive, 5} -]). ----- - -Cowboy implements the keep-alive mechanism by reusing -the same process for all requests. This allows Cowboy -to save memory. This works well because most code will -not have any side effect impacting subsequent requests. -But it also means you need to clean up if you do have -code with side effects. The `terminate/3` function can -be used for this purpose. - -=== Pipelining (HTTP/1.1) - -While HTTP is designed as a sequential protocol, with -the client sending a request and then waiting for the -response from the server, nothing prevents the client -from sending more requests to the server without waiting -for the response, due to how sockets work. The server -still handles the requests sequentially and sends the -responses in the same order. - -This mechanism is called pipelining. It allows reducing -latency when a client needs to request many resources -at the same time. This is used by browsers when requesting -static files for example. - -This is handled automatically by the server. - -=== Asynchronous requests (HTTP/2) - -In HTTP/2, the client can send a request at any time. -And the server can send a response at any time too. - -This means for example that the client does not need -to wait for a request to be fully sent to send another, -it is possible to interleave a request with the request -body of another request. The same is true with responses. -Responses may also be sent in a different order. - -Because requests and responses are fully asynchronous, -Cowboy creates a new process for each request, and these -processes are managed by another process that handles the -connection itself. - -HTTP/2 servers may also decide to send resources to the -client before the client requests them. This is especially -useful for sending static files associated with the HTML -page requested, as this reduces the latency of the overall -response. Cowboy does not support this particular mechanism -at this point, however.