This implements the upcoming draft-13
but has bits to make it work with draft-02
that most (all?) Chromium versions use.
Data and events are not going through
cowboy_stream beyond init. Since this
approach appears to work well it may
be a good idea to do the same for
Websocket over HTTP/2+ and improve
its performance.
`perf` has shown that Cowboy spends a lot of time
cancelling and starting this timer. Instead of resetting
for every data received, we now only reset a field in the
state.
Before it was working like this:
- start idle timeout timer
- on trigger, close the connection
- on data, cancel and start again
Now it's working like this:
- start idle timeout timer for a tenth of its duration, with tick number = 0
- on trigger, if tick number != 10
- start the timer again, again for a tenth of its duration
- increment tick number
- on trigger, if tick number = 10
- close the connection
- on data, set tick number to 0
It benchmarks binary, ascii, mixed and japanese data
using Websocket and Websocket over HTTP/2.
HTTP/2 options get set to ensure that performance is
better than the default HTTP/2 options.
It switches to Gun and Ranch branches that include
fixes that are required for tests to complete successfully.
This includes Websocket over HTTP/3.
Since quicer, which provides the QUIC implementation,
is a NIF, Cowboy cannot depend directly on it. In order
to enable QUIC and HTTP/3, users have to set the
COWBOY_QUICER environment variable:
export COWBOY_QUICER=1
In order to run the test suites, the same must be done
for Gun:
export GUN_QUICER=1
HTTP/3 support is currently not available on Windows
due to compilation issues of quicer which have yet to
be looked at or resolved.
HTTP/3 support is also unavailable on the upcoming
OTP-27 due to compilation errors in quicer dependencies.
Once resolved HTTP/3 should work on OTP-27.
Because of how QUIC currently works, it's possible
that streams that get reset after sending a response
do not receive that response. The test suite was
modified to accomodate for that. A future extension
to QUIC will allow us to gracefully reset streams.
This also updates Erlang.mk.
Note: This commit makes cowboy depend on cowlib master.
Graceful shutdown for HTTP/2:
1. A GOAWAY frame with the last stream id set to 2^31-1 is sent and a
timer is started (goaway_initial_timeout, default 1000ms), to wait
for any in-flight requests sent by the client, and the status is set
to 'closing_initiated'. If the client responds with GOAWAY and closes
the connection, we're done.
2. A second GOAWAY frame is sent with the actual last stream id and the
status is set to 'closing'. If no streams exist, the connection
terminates. Otherwise a second timer (goaway_complete_timeout,
default 3000ms) is started, to wait for the streams to complete. New
streams are not accepted when status is 'closing'.
3. If all streams haven't completed after the second timeout, the
connection is forcefully terminated.
Graceful shutdown for HTTP/1.x:
1. If a request is currently being handled, it is waited for and the
response is sent back to the client with the header "Connection:
close". Then, the connection is closed.
2. If the current request handler is not finished within the time
configured in transport option 'shutdown' (default 5000ms), the
connection process is killed by its supervisor (ranch).
Implemented for HTTP/1.x and HTTP/2 in the following scenarios:
* When receiving exit signal 'shutdown' from the supervisor (e.g. when
cowboy:stop_listener/3 is called).
* When a connection process is requested to terminate using
sys:terminate/2,3.
LH: Edited tests a bit and added todos for useful tests to add.
This reduces the number of times we need to ask for more packets,
and as a result we get a fairly large boost in performance,
especially with HTTP/1.1.
Unfortunately this makes Cowboy require at least Erlang/OTP 21.3+
because the ssl application did not have active,N. For simplicity
the version required will be Erlang/OTP 22+.
In addition this change improves hibernate handling in
cowboy_websocket. Hibernate will now work for HTTP/2 transport
as well, and stray or unrelated messages will no longer cancel
hibernate (the process will handle the message and go back into
hibernation).
Thanks go to Stressgrid for benchmarking an early version of this
commit: https://stressgrid.com/blog/cowboy_performance_part_2/
For long-running connections it was possible for the connection
window to become larger than allowed by the protocol because the
window increases claimed by stream handlers were never reclaimed
even if no data was consumed.
The new code applies heuristics to fix this and reduce the number
of WINDOW_UPDATE frames that are sent. It includes six new options
to control that behavior: margin, max and threshold for both the
connection and stream windows. The margin is some extra space
added on top of the requested read size. The max is the maximum
window size at any given time. The threshold is a minimum window
size that must be reached before we even consider sending more
WINDOW_UPDATE frames. We also avoid sending WINDOW_UPDATE frames
when there is already enough space in the window, or when the
read size is 0.
Cowlib is set to master until a new tag is done.
The examples test suite is only useful once in a while
in order to know whether examples were broken, for example
before issuing a release.
The new ws_autobahn test suite isolates the autobahn test
suite so that it can be ignored by default. It's only
useful to run it when working on the Websocket code or
before issuing a release.