-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
Filter mechanism for server transport creation and deletion #2132
Comments
Had a discussion with @louiscryan and @ejona86. We agree that the decoration pattern exposes too much of the transport API, thus it's undesirable. Instead, we consider using interface ServerTransportFilter {
Context transportCreated(Attributes transportAttrs);
}
This interface is very small and doesn't expose transport API. TBD:
|
@lukaszx0 I would like to hear your opinion on removing |
@zhangkun83 sorry for missing original mention. I like the idea of using context for everything and removing Looping in @jhump who might have opinions on the main issue discussed here. |
Haven't thought about it very deeply. My initial reaction is "no strong opinion". Using context instead of call attributes seems fine to me. |
@ejona86 @louiscryan and I had a further discussion about this issue. We feel that the Context-based interface earlier has two issues:
Our consensus is that we keep abstract class ServerTransportFilter {
// Called after all handshake (e.g., SSL) is done.
// transportAttrs: contains original transport information, such as
// socket address and SSL context.
// return: will be merged into ServerCall.attrs
Attributes transportReady(Attributes transportAttrs) {
return transportAttrs;
}
// attrs: contains all the data returned by transportReady of the same filter
void transportTerminated(Attributes attrs);
} @lukaszx0 WRT Attributes vs. Context, we have drawn a clear line between them. I hope this addresses your confusion.
ServerInterceptor is the one that consumes Attributes and produces Context. |
Called whenever a ServerTransport is ready and terminated. Has the ability to modify transport attributes, which ServerCall.attributes() are based on. Related changes: - Attribute keys for remote address and SSL session are now moved from ServerCall to a neutral place io.grpc.Grpc, because they can also be used from ServerTransportFilter, and probably will be used on the client-side too. The old keys on ServerCall is marked deprecated and are equivalent to the new keys. - Added transportReady() to ServerTransportListener. Resolves grpc#2132
Reopening this issue to track the experimental status of ServerTransportFilter. |
Created #2577 for experimental tracking. |
I can't figure out how ServerTransportFilter is useful in its current form, since it provides so little information about the server transport from which to make any meaningful decision. In its current implementation, the only information I can learn about the transport is the client's remote address. The only use I can see for a ServerTransportFilter is as a way to note that a connection starts and stops existing. Perhaps that is the only purpose. |
I've written a When combined with a server interceptor, you can use the session UUID to write session aware gRPC services. |
@rmichela, you should be very careful with that session stuff. gRPC does not provide that feature in its API on purpose, because gRPC does not provide those guarantees. For example, L7 load balancers will demolish such transport=session assumptions. gRPC may also disconnect the transport whenever it wishes, which could disturb a login flow. |
Very true. Sessions in RPC always come with a few caveats. If your load balancer is not sticky, most bets are off unless you are persisting session in some kind of data store. gRPC dropping and reconnecting the transport is something i hadn't considered. Perhaps the session ID should be established by a client interceptor. Even with a client interceptor, session persistence would be needed in the absence of a sticky session. |
To support a per-connection throttling mechanism used inside google, gRPC needs to allow user to add filters to the server that:
I discussed a few options with @ejona86:
ServerInterceptor
The filter returns a
ServerInterceptor
when transport is created. The interceptor is transport-scoped, unlike ordinary interceptors that are service-scoped.Pros:
ServerInterceptor
for purposes thatServerInterceptor
is designed for (modifying ServerCall attributes etc).Cons:
ServerInterceptor
. @ejona86 thinks bondingServerInterceptor
to a transport is seemingly generic but actually an ad-hoc solution for a particular problem. I don't necessarily agree though.Decorating transport
The filter returns a decorated
ServerListener
at registration. Through a few more layers of wrapping, the filter would be able to decorateServerListener.transportCreated(),
ServerTransportListener.transportTerminated() andServerStream.attributes()
.Pros:
Cons:
ServerStream
instead ofServerCall
. It would be ideal to just decorateServerCall
, which is whatServerInterceptor
does.ServerInterceptor
currently is per-service, but our use case need it to be per-connection.Ad-hoc
Just for our original requirements, the filter would return per-transport attributes that are to be merged into ServerCall attributes.
It probably won't work in this form, because the attributes such as peer security identity may not be available immediately after the transport is created, if the security handshake has not completed yet. On the other hand, the first two options can work around this situation by reading the attributes only when the first stream is created.
The text was updated successfully, but these errors were encountered: