proposal/G2-http3-protocol.md

155 lines
7.2 KiB
Markdown

G2: gRPC over HTTP/3
----
* Author(s): [James Newton-King](https://github.com/jamesnk)
* Approver: ejona86
* Status: Implemented
* Implemented in: grpc-dotnet
* Last updated: 2021-08-25
* Discussion at: https://groups.google.com/g/grpc-io/c/b1dWReBGyX4
## Abstract
HTTP/3 is the third and upcoming major version of the Hypertext Transfer Protocol
used to exchange information on the World Wide Web, alongside HTTP/1.1 and HTTP/2.
This proposal is for how the gRPC protocol should run on top of the HTTP/3 protocol.
## Background
gRPC uses HTTP semantics but requires HTTP/2 for some features. HTTP/3 offers the
same capabilities as HTTP/2, enabling all gRPC scenarios, along with new benefits
offered by HTTP/3:
* Faster connection negotiation in fewer round-trips.
* Improved experience when there is connection packet loss.
* Client supports transitioning between networks.
[PROTOCOL-HTTP2.md](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md)
covers gRPC's HTTP semantics, along with some content that is specific to HTTP/2.
Either this document should be generalized to include HTTP/2 and HTTP/3 information,
or a new gRPC over HTTP/3 protocol document should be created.
### Related Proposals:
n/a
## Proposal
### HTTP semantics
The shape of gRPC HTTP requests and responses are unchanged in HTTP/3. The
content in [PROTOCOL-HTTP2.md](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md)
that covers requests and responses can be referred to directly, without any
duplication.
Notably, unlike gRPC-Web, the content-type of `application/grpc` is unchanged. Apps
are still communicating with gRPC, but over HTTP/3 instead of HTTP/2.
### Transport mapping
The gRPC over HTTP/2 specification [discusses HTTP2 transport mapping](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#http2-transport-mapping).
The content discussed is mostly applicable to HTTP/3.
#### Stream Identification
HTTP/3 stream IDs function largely the same as HTTP/2 stream IDs.
#### Data frames
The relationship between `DATA` frames and length prefixed messages are unchanged in HTTP/3.
#### Errors
HTTP/3 [has different error codes](https://quicwg.org/base-drafts/draft-ietf-quic-http.html#section-8.1)
from HTTP/2. HTTP/3 errors are sent via QUIC frames instead of an `RST_STREAM` HTTP frame.
HTTP/3 errors are used in three situations:
* Abruptly terminating streams
* Aborting reading of streams
* Immediately closing HTTP/3 connections
HTTP3 Code|HTTP2 Code|GRPC Code
----------|----------|-----------
H3_NO_ERROR(0x0100)|NO_ERROR(0)|INTERNAL - An explicit GRPC status of OK should have been sent but this might be used to aggressively [lameduck](https://landing.google.com/sre/sre-book/chapters/load-balancing-datacenter/#identifying-bad-tasks-flow-control-and-lame-ducks-bEs0uy) in some scenarios.
H3_GENERAL_PROTOCOL_ERROR(0x0101)|PROTOCOL_ERROR(1)|INTERNAL
H3_INTERNAL_ERROR(0x0102)|INTERNAL_ERROR(2)|INTERNAL
H3_STREAM_CREATION_ERROR(0x0103)|n/a|INTERNAL
H3_CLOSED_CRITICAL_STREAM(0x0104)|n/a|INTERNAL
H3_FRAME_UNEXPECTED(0x0105)|FRAME_SIZE_ERROR|INTERNAL
H3_FRAME_ERROR(0x0106)|FRAME_SIZE_ERROR|INTERNAL
H3_EXCESSIVE_LOAD(0x0107)|ENHANCE_YOUR_CALM|RESOURCE_EXHAUSTED ...with additional error detail provided by runtime to indicate that the exhausted resource is bandwidth.
H3_ID_ERROR(0x0108)|n/a|INTERNAL
H3_SETTINGS_ERROR(0x0109)|SETTINGS_TIMEOUT(4)|INTERNAL
H3_MISSING_SETTINGS(0x010a)|SETTINGS_TIMEOUT(4)|INTERNAL
H3_REQUEST_REJECTED(0x010b)|REFUSED_STREAM|UNAVAILABLE - Indicates that no processing occurred and the request can be retried, possibly elsewhere.
H3_REQUEST_CANCELLED(0x010c)|CANCEL(8)|Mapped to call cancellation when sent by a client.Mapped to CANCELLED when sent by a server. Note that servers should only use this mechanism when they need to cancel a call but the payload byte sequence is incomplete.
H3_REQUEST_INCOMPLETE(0x010d)|n/a|INTERNAL
H3_MESSAGE_ERROR(0x010e)|n/a|INTERNAL
H3_CONNECT_ERROR(0x010f)|CONNECT_ERROR|INTERNAL
H3_VERSION_FALLBACK(0x0110)|n/a|INTERNAL
n/a|FLOW_CONTROL_ERROR(3)|INTERNAL
n/a|STREAM_CLOSED|No mapping as there is no open stream to propagate to. Implementations should log.
n/a|COMPRESSION_ERROR|INTERNAL
n/a|INADEQUATE_SECURITY| PERMISSION_DENIED … with additional detail indicating that permission was denied as protocol is not secure enough for call.
#### Connection management
`GOAWAY` and `PING` frames exist in HTTP/3 and serve the same purpose as in HTTP/2.
One notable difference is the `GOAWAY` frame in HTTP/2 reports the last
successfully processed stream ID. In HTTP/3 the `GOAWAY` frame ID value must be greater
than the last successfully processed stream ID.
### Exceeding deadlines
When an RPC has exceeded its deadline, the server will reset the stream. In HTTP/2, a stream
is reset using the `RST_STREAM` frame. The `RST_STREAM` frame doesn't exist in HTTP/3.
Instead, this action is performed using a QUIC frame, called `RESET_STREAM`.
| | Frame | Error code | Layer
----------------------------|--------------|------------------------------|----------
Deadline exceeded HTTP/2 | RST_STREAM | CANCEL(8) | HTTP
Deadline exceeded HTTP/3 | RESET_STREAM | H3_REQUEST_CANCELLED(0x010c) | QUIC
[RESET_STREAM](https://www.rfc-editor.org/rfc/rfc9000.html#name-reset_stream-frames) abruptly
terminates sending on a stream. An important difference between HTTP/2 and
HTTP/3 is frames are received out-of-order. Because of this, a `RESET_STREAM` sent after a
completed response could still result in the response being aborted.
HTTP/3 also has the QUIC `STOP_SENDING` frame. This frame is sent by the server when a
stream's response side completes before the request side. Using `STOP_SENDING` alone isn't
appropriate for a deadline exceeded, because both stream directions should be aborted.
However, `STOP_SENDING` should be sent along with `RESET_STREAM` if the deadline is exceeded
while the request side is in-progress.
### HTTP/3 negotation
A client and server both need to support HTTP/3 for it to be used. There are two common
scenarios for establishing an HTTP/3 connection:
* gRPC client uses TLS and is configured in advance to only use HTTP/3. The client starts a
QUIC+HTTP/3 connection to server. If the server doesn't support HTTP/3 then the connection
fails.
* gRPC client uses TLS and is configured to use HTTP/2 or greater. In this case an initial
HTTP/2 call is made, server returns response with an `alt-svc` header that tells the client
that HTTP/3 is available. HTTP/2 connection is replaced with QUIC+HTTP/3 and future calls
use HTTP/3. If the server doesn't support HTTP/3 then the client continues to use HTTP/2.
HTTP/3 requires TLS and will never be used by an insecure channel.
API for configuring channel HTTP negotation behavior is up to implementations.
## Rationale
HTTP/3 is an upcoming Internet Protocol. There needs to be a standardized agreement for how
gRPC over HTTP/3 works to maintain interoperability in the gRPC eco-system.
## Implementation
A trial implementation in grpc-dotnet is underway. .NET 6 is adding preview support for
HTTP/3 to the .NET server and client. grpc-dotnet leverages that underlying HTTP/3 support.
## Open issues (if applicable)
n/a