Service Mesh (ASM) allows you to set matching conditions for the keys and values of headers. This way, ASM can dynamically redirect traffic based on request headers. This topic describes how to redirect the traffic of applications in ASM based on headers.
Obtain headers on the gRPC server and client
Obtain headers on the gRPC server
Basic methods
Use Java to implement the basic method to obtain headers on the gRPC server.
Implement the
interceptCall(ServerCall<ReqT, RespT> call,final Metadata m,ServerCallHandler<ReqT, RespT> h)
method of theServerInterceptor
operation. Then, run theString v = m.get(k)
command to obtain headers on the server. The type of the input parameter of theget()
method isMetadata.Key<String>
.Use Go to implement the basic method to obtain headers on the gRPC server.
Implement the
metadata.FromIncomingContext(ctx)(md MD, ok bool)
method. The format of MD ismap[string][]string
.Use Node.js to implement the basic method to obtain headers on the gRPC server.
Implement the
call.metadata.getmap()
method. The type of the returned value is[key: string]: MetadataValue
. The type ofMetadataValue
isstring/Buffer
.Use Python to implement the basic method to obtain headers on the gRPC server.
Implement the
context.invocation_metadata()
method. The returned value is a two-tuple array in the format of('k','v')
. The key-value pair can be obtained fromm.key, m.value
.
Unary RPC
Use Java to implement the unary remote procedure call (RPC) method to obtain headers on the server.
The headers are intercepted.
Use Go to implement the unary RPC method to obtain headers on the server.
Call
metadata.FromIncomingContext(ctx)
in the method. The value of the ctx parameter is obtained from the input parameter of the Talk method.Use Node.js to implement the unary RPC method to obtain headers on the server.
Call
call.metadata.getMap()
in the method.Use Python to implement the unary RPC method to obtain headers on the server.
Call
context.invocation_metadata()
in the method.
Server streaming RPC
Use Java to implement the server streaming RPC method to obtain headers on the server.
The headers are intercepted.
Use Go to implement the server streaming RPC method to obtain headers on the server.
Call
metadata.FromIncomingContext(ctx)
in the method. You can call thestream.Context()
method to obtain the value of thectx
parameter from the input parameterstream
of the TalkOneAnswerMore method.Use Node.js to implement the server streaming RPC method to obtain headers on the server.
Call
call.metadata.getMap()
in the method.Use Python to implement the server streaming RPC method to obtain headers on the server.
Call
context.invocation_metadata()
in the method.
Client streaming RPC
Use Java to implement the client streaming RPC method to obtain headers on the server.
The headers are intercepted.
Use Go to implement the client streaming RPC method to obtain headers on the server.
Call
metadata.FromIncomingContext(ctx)
in the method. You can call thestream.Context()
method to obtain the value of thectx
parameter from the input parameterstream
of the TalkMoreAnswerOne method.Use Node.js to implement the client streaming RPC method to obtain headers on the server.
Call
call.metadata.getMap()
in the method.Use Python to implement the client streaming RPC method to obtain headers on the server.
Call
context.invocation_metadata()
in the method.
Bidirectional streaming RPC
Use Java to implement the bidirectional streaming RPC method to obtain headers on the server.
The headers are intercepted.
Use Go to implement the bidirectional streaming RPC method to obtain headers on the server.
Call
metadata.FromIncomingContext(ctx)
in the method. You can call thestream.Context()
method to obtain the value of thectx
parameter from the input parameterstream
of the TalkBidirectional method.Use Node.js to implement the bidirectional streaming RPC method to obtain headers on the server.
Call
call.metadata.getMap()
in the method.Use Python to implement the bidirectional streaming RPC method to obtain headers on the server.
Call
context.invocation_metadata()
in the method.
Send headers from the client
Basic methods
Use Java to implement the basic method to send headers from the client.
Implement the
interceptCall(MethodDescriptor<ReqT, RespT> m, CallOptions o, Channel c)
method of theClientInterceptor
operation. Implement thestart((Listener<RespT> l, Metadata h))
method of theClientCall<ReqT, RespT>
type. Then, runh.put(k, v)
to send headers on the client. The type of the input parameterk
ofput
isMetadata.Key<String>
, and that of the input parameterv
isString
.Use Go to implement the basic method to send headers from the client.
metadata.AppendToOutgoingContext(ctx,kv ...) context.Context
Use Node.js to implement the basic method to send headers from the client.
metadata=call.metadata.getMap()metadata.add(key, headers[key])
Use Python to implement the basic method to send headers from the client.
Set the variable in the
metadata_dict = {}
command in the following format:metadata_dict[c.key] = c.value
. Convert the type of data in the metadata_dict array tolist tuple
by usinglist(metadata_dict.items())
.
Unary RPC
Use Java to implement the unary RPC method to send headers from the client.
The headers are intercepted.
Use Go to implement the unary RPC method to send headers on the client.
Call
metadata.AppendToOutgoingContext(ctx,kv)
in the method.Use Node.js to implement the unary RPC method to send headers from the client.
Call the basic method.
Use Python to implement the unary RPC method to send headers from the client.
Call the basic method.
Server streaming RPC
Use Java to implement the server streaming RPC method to send headers from the client.
The headers are intercepted.
Use Go to implement the server streaming RPC method to send headers from the client.
Call
metadata.AppendToOutgoingContext(ctx,kv)
in the method.Use Node.js to implement the server streaming RPC method to send headers from the client.
Call the basic method.
Use Python to implement the server streaming RPC method to send headers from the client.
Call the basic method.
Client streaming RPC
Use Java to implement the client streaming RPC method to send headers from the client.
The headers are intercepted.
Use Go to implement the client streaming RPC method to send headers from the client.
Call
metadata.AppendToOutgoingContext(ctx,kv)
in the method.Use Node.js to implement the client streaming RPC method to send headers from the client.
Call the basic method.
Use Python to implement the client streaming RPC method to send headers from the client.
Call the basic method.
Bidirectional streaming RPC
Use Java to implement the bidirectional streaming RPC method to send headers from the client.
The headers are intercepted.
Use Go to implement the bidirectional streaming RPC method to send headers from the client.
Call
metadata.AppendToOutgoingContext(ctx,kv)
in the method.Use Node.js to implement the bidirectional streaming RPC method to send headers from the client.
Call the basic method.
Use Python to implement the bidirectional streaming RPC method to send headers from the client.
Call the basic method.
Propaganda Headers
In Tracing Analysis, upstream link metadata must be passed through to the downstream to obtain the complete information of a trace. Therefore, the tracing-related header information that is obtained on the server must be passed through to the client that sends the request to the downstream.
The operations of the communication models that are implemented by using Go, Node.js, and Python can receive headers. Therefore, the following three actions can be implemented in order by using the operations of the four communication models: First, the server reads the headers. Then, the server passes the headers. Last, the client sends the headers.
The operations of the communication models that are implemented by using Java cannot be used to propaganda headers in an ordered process. This is because Java reads and writes headers by using two interceptors. Only the read interceptor obtains the unique ID of the tracing. In addition, gRPC services may receive and send requests at the same time. As a result, the two interceptors cannot be connected by using caching, which is the most intuitive method to show traces.
Java uses Metadata-Context Propagation to trace headers.
When the server interceptor reads headers, the headers
are written into Context by using ctx.withValue(key, metadata)
. The type of the key parameter is Context.Key<String>
. Then, the client interceptor reads the headers
from Context by using key.get()
. By default, the get method uses Context.current()
. This ensures that the same context is used when headers are read and written.
When headers can be propagandized, you can trace the request and response messages between the gRPC client and server.
Deploy and verify the topology of an ASM instance
Before you can redirect traffic, you must deploy and verify the topology of the ASM instance in which your application resides. Make sure that the topology of the ASM instance works as expected.
The tracing folder of the sample project contains deployment scripts in Java, Go, Node.js, and Python. In this example, the Go deployment script is used to deploy and verify the topology of the ASM instance.
cd go
# Deploy the topology of the ASM instance.
sh apply.sh
# Verify the topology of the ASM instance.
sh test.sh
If no exceptions occur, the topology of the ASM instance works as expected.
The following figure shows the deployed topology of the ASM instance.
Redirect traffic
You can create a virtual service in ASM to set matching conditions for the keys and values of headers. This way, ASM can dynamically redirect traffic based on request headers. Furthermore, You can shape the traffic of your application in a fine-grained way based on the gRPC version and gRPC API operations. For more information, see Shape traffic to gRPC servers. The following example shows you how to create a virtual service to direct all the requests of which the headers contain server-version=go
to the Go-based gRPC server.
Log on to the ASM console.
In the left-side navigation pane, choose .
On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column.
On the details page of the ASM instance, choose in the left-side navigation pane. On the page that appears, click Create from YAML.
On the Create page, select a namespace as required, copy the following content to the code editor, and then click Create.
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: namespace: grpc-best name: grpc-server-vs spec: hosts: - "*" gateways: - grpc-gateway http: - match: - headers: server-version: exact: go route: - destination: host: grpc-server-svc subset: v2 weight: 100