Set up Header Propagation
Overview
Signadot can dynamically route http and gRPC requests to specific versions of the destination Service using Signadot DevMesh or a Service Mesh. A specific request header value is used to determine where to route a request. By default requests are routed to the baseline version of Services. If the header contains context for a specific Sandbox, then the request is routed to the forked version of the Service in that Sandbox.
Consider an example where you have Services A, B and C and we have a fork, Service B" in a Sandbox. In the request flow diagram shown below, the dotted orange lines show a request that includes a header with a reference to the Sandbox. This request is routed to the forked version Service B" that's part of the Sandbox. All requests without this header, will flow through Service B.
For this to work, a pre-requisite is for Service A to propagate specific request headers from the incoming requests to all outgoing requests. This is called context propagation. The sections below detail how Signadot makes use of context propagation and how to implement context propagation in your Services.
Header Propagation
The goal of context propagation is to ensure that this sandbox metadata survives every step of the subsequent chain of service-to-service requests, so that request routing can occur at any step.
Context propagation is commonly achieved using distributed tracing libraries because these libraries can often automatically instrument your code with minimal changes. They do this with request middleware layers that extract data from certain headers in all incoming requests, propagate that data throughout the function call stack, and add the same header values to all outgoing requests made from within that call stack. Note that this does not require using a trace backend, and simply adding the library / instrumenting code is sufficient to ensure that request context is propagated between services.
OpenTelemetry Standard Headers
By default, Signadot supports headers from the OpenTelemetry standard for request routing. If you are looking to route using custom non-standard headers, you can set that up as a custom header.
There are two mechanisms of propagation that are supported from the OpenTelemetry specification:
In both of these cases, a key named sd-routing-key
[^1] is used to persist information pertaining to Sandboxes. If you're making use of OpenTelemetry instrumentation in your services, baggage
and tracestate
headers are propagated automatically.
For several dynamic languages, there is auto-instrumentation possible that requires no code changes. Refer to OpenTelemetry docs for details. Sample code for implementing header propagation in various languages using OpenTelemetry can be found in this GitHub Repository.
Custom Headers
Prior to v0.19.1 of the Signadot Operator, the following headers were also used for routing by default:
uberctx-sd-routing-key
anduberctx-sd-sandbox
used by the Jaeger Tracing standard.ot-baggage-sd-routing-key
andot-baggage-sd-sandbox
used by Datadog's APM libraries.
In new versions of the operator, they must be specified as a custom header as shown below in order to be used.
If you are not using the above headers and are using a custom header that is
propagated between your microserivces, you can set that up at installation time
in the Signadot Operator using the routing.customHeaders
helm value. Any
headers you specify will be added to the routing layer, in addition to baggage
and tracestate
that are always enabled by default.
Message Queues
Message queue messages can use the same headers as above for routing. To learn more, refer to the documentation on message queues.