uber / tchannel

network multiplexing and framing protocol for RPC
MIT License
1.15k stars 129 forks source link

Formally support HTTP/1.1 Upgrade mechanism #1414

Closed Qix- closed 7 years ago

Qix- commented 7 years ago

I did a bit of searching and didn't seem to see any discussion about this, which surprised me.

Section 6.7 of the HTTP/1.1 specification defines a connection Upgrade mechanism to convert TCP connections that were originally HTTP requests to another protocol.

For example (from the spec):

Connection: upgrade
Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11

In our case, we would support an upgrade to a TChannel connection:

Connection: upgrade
Upgrade: TChannel/2.0, TChannel/1.0

Depending on which version the server supports, it'd upgrade to either TChannel 1.0 or 2.0 and respond with

HTTP/1.1 101 Switching Protocols
Connection: upgrade
Upgrade: TChannel/2.0

This would be a connection-related change in the specification and would simply require client libraries to check the hostname URI for a scheme, and in the event the scheme is http:// (and perhaps https://) then it should make a regular HTTP/1.1 request to the server with an upgrade request and fail if the corresponding server cannot upgrade. All existing configurations that do not specify a URI for connection (e.g. a simple hostname or IP) would be unaffected.

This change would allow us to multiplex several protocol types over one backend port (HTTP, HTTP2, TLS, WebSocket, TChannel, etc.) with minimal overhead.

Just a thought.


Side note: If we so choose, the IANA is open to third-party upgrade tokens. Since TChannel is somewhat of an established protocol with a proper specification and committee (Uber), they might be open to adding TChannel as a registered upgrade-able protocol (relevant RFC section). But that's not mandatory for TChannel to work over an upgraded connection.

prashantv commented 7 years ago

Hi Josh,

Using the HTTP Upgrade path is an interesting idea! We've thought about sharing a single port for multiple protocols -- Josh Corbin has prototyped a library that can actually detect and choose the right protocol. I think he had an example which could detect HTTP, TChannel or Redis, and automatically reply in the right protocol. This approach peeks at the first few bytes to decide the protocol.

The sniffing approach simplifies the ugprade process, since you don't need to integrate with HTTP libraries in each language (it's unclear whether all languages will support upgrading the connection and then hijacking the underlying TCP connection).

However, I don't think this is a real problem we're affected by right now, and so we shouldn't be prioritizing any work related to sharing the same port. Our discovery system supports multiple ports for a single task, and it's simpler + easier to debug when a single port only contains a single protocol. E.g., when using tcpdump, or tcap, you now have to differentiate the protocol, and it becomes even more complicated if you upgrade an existing HTTP connection, all the tools will need to understand that flow as well.

Given that we currently have HTTP and TChannel and don't have plans to add any completely different protocols (if we added HTTP2, it would probably use the same HTTP port and use the upgrade path), the complication in debugging and implementation seems more expensive than the cognitive cost of dealing with 2 ports.

Qix- commented 7 years ago

That's fair! I was also going the route of a de-multiplexer (like what Joshua was doing), but wanted to entertain the idea of a more 'formal' means to an end :)

Thanks for the response, Prashant!