5 ms·
Hey everyone, I've recently created an open source library on top of grpc-kotlin and grpc-java that allows you to propagate a context across microservice bounda
by reidbuzby 3y ago
Hey everyone, I've recently created an open source library on top of grpc-kotlin and grpc-java that allows you to propagate a context across microservice boundaries throughout an entire request lifetime. The existing io.grpc.Context (https://grpc.github.io/grpc-java/javadoc/io/grpc/Context.html https://grpc.github.io/grpc-java/javadoc/io/grpc/Context.htm...) only propagates a context across API boundaries within the same container and does not cross microservice boundaries.
It's called KonigKontext, check it out here: https://github.com/konigsoftware/konig-kontext https://github.com/konigsoftware/konig-kontext!
Example use cases include:
Propagating security principals, or user credentials and identifiers throughout an entire request lifetime across all of your microservices.
Propogating distributed tracing information. Set a request trace id upon receiving a request and later access that id in any downstream microservice.
However, Konig Kontext is built to support any type of context value, so it can be extended to fit any specific use cases as well.
Let me know what you think!
- jayd16 3y agoWhy not just add this stuff to the request itself?
- reidbuzby 3y agoDitto whats been said before. It can be very cumbersome to update multiple request/response types with new data especially if an intermediary service has no use for the data and is simply passing it through.
- rossjudson 3y agoIt avoids polluting your request classes with side channel details that your service may not even be concerned with at all; it makes for nice abstractions. It allows for the opaque propagation of side channel information, where intermediates don't need to know what's there. side-channel-with-well-defined-propagation-rules is pretty useful.
- jayd16 3y agoAdding hidden data to the request seems counter to the desire for a schema driven rpc. I guess it's a matter of taste whether some data is pollution or simply explicit. You're sending data that the service may or may not be concerned with whether its in the header or the body or some other side channel. Maybe my reaction is a question of purity. I don't really see why one would think a request body should be in the schema but we should leave other data out of the schema. Wouldn't every single argument point to consistency? I like gRPC and what it gives you. I personally would like that same explicit schema and type safety to apply to my tracing as well. Its interesting to me that others would draw a line.
- reidbuzby 3y agoYou do get the same explicit schema and type safety with this library. The context values can be typed using a protobuf message: https://github.com/konigsoftware/konig-kontext#protobuf-message-based-type https://github.com/konigsoftware/konig-kontext#protobuf-mess..., or any other type you'd like. Although you are right, it is not explicitly in the request schema but that's kinda the point.
- hamandcheese 3y agoDebug/tracing data is a great use case for context, for example. If propagating trace information has to be done manually, then you significantly weaken the utility of cross-service tracing. You'll always be questioning if lack of a trace means it didn't happen, or if it means someone forgot to pass along the trace context. This applies especially to grpc, where everything is optional. To be clear, I prefer explicit over implicit. But that doesn't always scale well to large orgs.
- jayd16 3y agoI think what's throwing me off is that the examples aren't just transparent things like debug/tracing. They mention credentials and user ids, which the app code can observe and rely on. The combination of out-of-band/out-of-schema data with APIs to set and get from app code seems like a bad match. I'd prefer if it was completely invisible to app code and existed only in interceptors.
- zeroxfe 3y agoBecause every single handler in a long chain of requests will have to explicitly support and propagate this data. The whole idea of a request context is to let you plumb low-cost metadata transparently through a call tree, and decouple your code from that metadata.
- jarym 3y agoVery well articulated and agree. It’s one of those things you eventually wish you had.
- no_circuit 3y agoThe header is fixed as konig-kontext-grpc-context [1]. Does that mean that you can only propagate one gRPC context object? Would it be possible to specify your own header string for the key, and have the interceptors support multiple keys? That sounds safer since the header name could both imply both the serialization and content-type, and Protobuf type_uri, etc. And sounds more useful since developers wouldn't need a catch-all type. [1] https://github.com/konigsoftware/konig-kontext/blob/84faa627f43445c7a3e0cad8b96f1fb768eac0ad/lib/src/main/kotlin/com/konigsoftware/kontext/KonigKontextKey.kt#L12 https://github.com/konigsoftware/konig-kontext/blob/84faa627...
- reidbuzby 3y agoSupport for multiple keys is in the works! See this issue for updates: https://github.com/konigsoftware/konig-kontext/issues/8 https://github.com/konigsoftware/konig-kontext/issues/8