-
Notifications
You must be signed in to change notification settings - Fork 248
G2: gRPC over HTTP/3 #256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
G2: gRPC over HTTP/3 #256
Changes from all commits
6bdfe05
d98a360
a278477
7280a58
55e5e98
280a1ff
4e383de
1ce2b8c
6cd60e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
G2: gRPC over HTTP/3 | ||
---- | ||
* Author(s): [James Newton-King](https://github.com/jamesnk) | ||
* Approver: ejona86 | ||
* Status: In review | ||
* 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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. QUIC always uses security (TLS) which means gRPC-over-http3 always requires certs/keys IIUC. Does it impact the gRPC API or the usage? To be addressed in this gRFC? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. HTTP/3 would never be negotated over an insecure connection. Scenarios would be:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think clients might introduce channel settings to give users the specify what protocol they want. For example:
|
||
|
||
n/a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lidizheng what about doing some python asyncio prototyping!? https://github.com/aiortc/aioquic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that building a MVP gRPC Python HTTP/3 on top of the
aioquic
library probably isn't that hard. Currently, gRPC Python uses gRPC Core as the transport layer, it's not that trivial to move existing code onto another transport library. I hope if we want to invest resources, we have a working architecture and aiming for long-term support.