-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
thrift_proxy: simple thrift router #3863
thrift_proxy: simple thrift router #3863
Conversation
Provides a very basic thrift router that can route to clusters based on method name only. A Thrift DecoderFilter interface is introduced, but the only available filter is the Router. The Network filter and router are capable of translating transports and protocols but presently cannot be configured to do so. Relates to envoyproxy#2247. *Risk Level*: low *Testing*: unit and integration testing *Docs Changes*: protobuf documentation updated *Release Notes*: introduced a basic thrift_proxy routing extension Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
My apologies that this turned out to be such a large change. In the |
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
@zuercher a bit of a pie in the sky question: would this be reusable within another filter? Lets say i've got incoming HTTP1.1 traffic, and I want to write a filter that decodes headers and then fans out to a thrift service to read/write something. Is that something you thought of or would it require a bit refactoring? cc: @fishcakez |
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'm half finished reading through this. I'll read the remaining half tomorrow.
} | ||
|
||
if (event == Network::ConnectionEvent::RemoteClose) { | ||
stats_.cx_destroy_local_with_active_rq_.inc(); |
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.
Is the logic for this reversed? Upon a remote close event, this is incrementing the cx_destroy_local_with_active_rq_
counter. Should it be the cx_destroy_remote_with_active_rq_
counter?
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.
Yes, but it also turns out that the connection pool will record these, so I'm going to remove this code.
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.
Er. Sorry. No the conn pool tracks upstream destroy with active request. I'll fix this.
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.
did a quick pass, will do another one tomorrow
|
||
// Route request to some upstream cluster. | ||
RouteAction route = 2 [(validate.rules).message.required = true, (gogoproto.nullable) = false]; | ||
; |
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.
nit: trailing ;
message RouteMatch { | ||
// If specified, the route must exactly match the request method name. As a special case, an | ||
// empty string matches any request method name. | ||
string method = 1; |
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.
is this case-sensitive?
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.
Yes.
} | ||
|
||
if (event == Network::ConnectionEvent::RemoteClose) { | ||
stats_.cx_destroy_local_with_active_rq_.inc(); |
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.
nit: return? given we know what the event is and it can't be something else
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
@rgs1 (re: filter making thrift requests from the http filter stack) I think you could reuse parts of this, but not the ConnManager/Router directly. To send thrift requests to an external server (for auth or whatever), you'd likely want to extend the approach in app_exception_impl.h/.cc with some kind of code generator that would consume Thrift IDL and generate code for objects that can marshal/unmarshal themselves to/from buffers via a Protocol instance. You need some kind of AsyncThriftClient that would handle the request encoding/response decoding and transport and such. You look at the ext_authz filter for more-or-less how that would look. |
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
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.
Aside from nits, I have one big question: in the situation where the upstream and downstream use the same Thrift protocol (but potentially different Thrift transports), is it possible to skip the parsing, callbacks, and re-encoding of the message?
/** | ||
* @return uint64_t the ID of the originating stream for logging purposes. | ||
*/ | ||
virtual uint64_t streamId() PURE; |
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.
Can this be a const
method?
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 have the same question about many of the other methods of this class.
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.
Some can be const, I'll update them.
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
The proxy has to modify the sequence id to avoid the situation where the same sequence id from separate downstream clients is sent to a single upstream (there's an outstanding TODO in the code to actually do this). Modifying the sequence id can (for, say, the compact protocol) change the size of the message, which may necessitate modifying the transport frame. For transports which report size (e.g. framed and header, but not unframed), I think that the mechanism for this would be:
|
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
ProtocolError = 7, | ||
InvalidTransform = 8, | ||
InvalidProtocol = 9, | ||
UnsupportedClientType = 10, |
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.
fbthrift
has a few more exception types than apache thrift
: https://github.com/facebook/fbthrift/blob/04ba53d4503d51a9a27f700b114eb7cea4678dc1/thrift/lib/cpp/TApplicationException.h#L57. Should these be supported too? As an example later in the code InternalError
could be replaced by more specific code such as LoadShedding
. Would that create sub-optimal experience for apache thrift
as the enum value would not exist in the client services logic? Without using the fbthrift
exception types there will be feature regressions for some client services as would no longer be able to differentiate.
Is apache thrift
being treated as the standard here when there are competing standards?
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 think short-term, we'll stick with the apache definitions. Longer term, we'll probably want to use internal identifiers for various error conditions and then provide a configuration point to control whether they get mapped to apache or fb's values.
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
Signed-off-by: Stephan Zuercher <stephan@turbinelabs.io>
Provides a very basic thrift router that can route to clusters
based on method name only. A Thrift DecoderFilter interface is
introduced, but the only available filter is the Router. The
Network filter and router are capable of translating transports
and protocols but presently cannot be configured to do so.
Relates to #2247.
Risk Level: low
Testing: unit and integration testing
Docs Changes: protobuf documentation updated
Release Notes: introduced a basic thrift_proxy routing extension
Signed-off-by: Stephan Zuercher stephan@turbinelabs.io