Skip to content
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

A73: Transport Selection #399

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
119 changes: 119 additions & 0 deletions A73-transport-selection.md
@@ -0,0 +1,119 @@
Transport Selection
----
* Author(s): dfawley
* Approver: roth, ejona86
* Status: Draft
* Implemented in: none
* Last updated: 2023-11-07
* Discussion at: TODO: TBD

## Abstract

A standardized method to dynamically choose between multiple transports.

## Background

gRPC predominately uses HTTP/2 over TCP to communicate between client and
server. In some implementations, there are existing methods for circumenting
this to instead use an in-process transport. There are also use cases that would
like to take advantage of alternate transports, e.g.
[QUIC+HTTP/3](https://github.com/grpc/proposal/blob/master/G2-http3-protocol.md)
and a way of communicating over shared memory (design TBD).

### Related Proposals:

* [L37: Go Custom Transports](https://github.com/grpc/proposal/pull/103)
(pending)
* [G2: gRPC over
HTTP/3](https://github.com/grpc/proposal/blob/master/G2-http3-protocol.md)
* [A6: Client
Retries](https://github.com/grpc/proposal/blob/master/A6-client-retries.md)

## Proposal

This proposal is for a standard way of selecting which transport to use in gRPC
clients and servers. The exact details will be left up to gRPC implementations
to decide; only the high-level method is included in this design.

Some additional design goals of this proposal:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is awkward. It is in the proposal section, and defines a mix of goals and design choices. I think "goals" isn't the right word here, as these are part of the proposal itself. Goals shouldn't be in "Proposal" anyway.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved into a sub-section about transports.


1. Transport and stream APIs should expose gRPC semantics as defined in the
(pending) [Call Semantics
Specification](https://github.com/grpc/grpc/pull/15460) and hide HTTP/2
semantics and grpc's wire protocol semantics.
1. Stream APIs should support object-based messages to facilitate an in-process
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the end, it seems you're expecting to make a copy here. I'd suggest mentioning copying objects as the alternative to serialize+deserialize. Otherwise it isn't really clear what you're talking about. On the face of it it looked like you'd just pass the object from client to server, but that is fundamentally broken unless the objects are immutable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mentioned "copying".

transport that avoids serializing and deserializing in order to transmit a
message.
* Note that some features, e.g. [client
retries](https://github.com/grpc/proposal/blob/master/A6-client-retries.md)
may require byte-based message support due to message caching. Such
features may be unsupported for transports that cannot also support
byte-based messages.
1. The API for creating transports will encapsulate the logic for connecting to
addresses (e.g. net.Dial) as an implementation detail of the transport.
Similarly, credentials handshaking must happen within the transport.

The following are the high level components of this design:

* Client: Name Resolvers and LB policies specify an address _type_ for every
address.

* Server: Users configure a listening address and corresponding address type.

* Client and Server: A registry is used to determine how to create transports
for each address type.

* Client and Server: Define an API for transports and streams. As mentioned
above, these APIs should expose gRPC semantics and not HTTP/2 semantics. The
specifics of the APIs will be left up to the individual gRPC client library
authors.

### Client-Side

Addresses produced by a name resolver or provided to the channel by the LB
policy will contain an indicator of the address type. This could be a separate
field in a struct, or via the language's type system, or through encoding of the
address itself (e.g. using a URI like `"tcp:127.0.0.1:8080"`). A registry or
similar mechanism containing a mapping from address types to transport factories
will be used to determine how to create a transport for each address.

### Server-Side

Servers wishing to use a specific type of transport listener will specify the
address type along with the address to listen on. As with client addresses, this
could be a field in a struct, types, or by using a URI. Also like client address
types, the listener's address type will be looked up in a registry to find a
listener factory. The constructed listener will produce transports for new
connections satisfying a common interface.

### Temporary environment variable protection

Since all transport selection logic takes place in code and is not configured by
I/O, no environment variable is needed.

## Rationale

Alternatives considered:

* Hardcode other transports, like the in-memory transport. Example
`NewInMemoryChannel()`.

This does not allow as much flexibility and requires recompilation to change
the way channels are created.

* Require byte-based transports.

This does not allow for a more efficient in-memory transport that is capable
of copying proto messages rather than serializing and deserializing.

* Decide the transport directly when the channel is created, rather than
allowing the resolver and balancer to influence it.

This would have a simpler API, however, it would require each channel to use
only a single transport. The proposed design enables a channel with different
types of connections.

## Implementation

As this is a high-level, cross-language design, implementation design and
details will be left up to the gRPC library authors.