Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Envoy ext_proc session affinity

Runnable demonstration of envoyproxy/envoy#46159. It shows that Envoy's existing gRPC client and cluster hash policies can keep requests with the same downstream session key on the same external processor endpoint.

The demo runs stock Envoy with two Go ext_proc servers. Each server returns an immediate response identifying itself and the gRPC initial metadata it received, making endpoint selection visible.

Topology

                                      Envoy
                       +----------------------------------+
                       |                                  |
client -- x-session-id | :10080  ext_proc_header cluster  |
                       |          RING_HASH(header)       |
                       |                                  |
client -- session_id   | :10081  ext_proc_cookie cluster  |
          cookie       |          RING_HASH(cookie)       |
                       |                                  |
                       +----------------------------------+
                                        |
                                        | ring-hash selects one endpoint
                                        |
                                        +---------> +----------------------+
                                        |           | processor-a :50051   |
                                        |           +----------------------+
                                        |
                                        +---------> +----------------------+
                                                    | processor-b :50051   |
                                                    +----------------------+

Both listeners send request headers to the ext_proc filter. Both clusters contain the same two Go gRPC processors; they differ only in the hash policy used to select one processor.

Expected flow

The header-affinity listener on port 10080 copies x-session-id into the ext_proc gRPC initial metadata. The Envoy gRPC client creates the ext_proc request with that metadata, and the ext_proc_header cluster hashes its x-session-id header with RING_HASH.

The cookie-affinity listener on port 10081 copies the downstream cookie header. Its cluster uses the passive session_id cookie hash policy. Envoy does not generate or return this cookie; the downstream client supplies it.

downstream session key
  -> GrpcService.initial_metadata
  -> gRPC request header or cookie
  -> cluster HttpProtocolOptions.hash_policy
  -> ring-hash endpoint selection
  -> processor-a or processor-b
  -> HTTP 200 immediate response containing processor=<selected ID>

For a fixed key and fixed healthy endpoint set, each request should hash to the same processor. A different key may select either processor. The processors return an immediate response so the selected endpoint is directly observable; the route's fallback 204 response is not the behavior under test.

Run

Warning

docker compose up --build downloads and executes container images from the internet. Review the Dockerfile, Compose configuration, image tags, and Go dependencies first, and run this demo only in an isolated, non-production environment.

Start Envoy and both processors:

make up

In another shell, show how several session keys map to the two processors:

make observe

Repeated requests with one key must remain on exactly one processor:

make check SESSION=session-1

Measure both affinity paths across multiple sessions:

make measure SESSIONS=32 REQUESTS_PER_SESSION=5

Assertions and measurement

For each affinity mode, the measurement performs these steps:

  1. Generate SESSIONS distinct keys: session-000, session-001, and so on.
  2. Send REQUESTS_PER_SESSION sequential requests for each key.
  3. Require every response to be HTTP 200 and contain a non-empty processor=<ID> field.
  4. Build the set of observed processor IDs for each session.
  5. Count the session as an affinity_violation when that set contains more than one ID.
  6. Require zero affinity violations and exactly EXPECTED_PROCESSORS distinct processors overall.

The second assertion ensures this two-processor demo does not accidentally pass while only one processor is serving traffic. The per-processor request and distinct-session counts expose the distribution without requiring a perfectly even split.

A successful run looks like this (the distribution varies):

mode=header sessions=32 requests_per_session=5 total_requests=160 processors_observed=2 affinity_violations=0
processor=processor-a requests=85 sessions=17
processor=processor-b requests=75 sessions=15
mode=cookie sessions=32 requests_per_session=5 total_requests=160 processors_observed=2 affinity_violations=0
processor=processor-a requests=85 sessions=17
processor=processor-b requests=75 sessions=15

Try the individual paths:

make header SESSION=session-1
make cookie SESSION=session-1
make missing

The exact processor selected for a key is not important. The invariant is that repeated requests with the same key select the same processor while both endpoints are healthy and the cluster membership is unchanged. The measurement deliberately sends requests sequentially; it measures endpoint affinity and endpoint participation, not throughput, latency, failover, or remapping after membership changes.

Stop the demo with Ctrl-C, then remove its containers and network:

make down

Candidate documentation and tests

The prepared Envoy branch adds documentation and integration coverage without changing production behavior:

https://github.com/envoyproxy/envoy/compare/main...dio:envoy:ext-proc-session-affinity

It covers header affinity, passive-cookie affinity, and requests without an affinity key. The cluster-level approach applies to the Envoy gRPC client, not the native Google gRPC client.

About

Runnable Envoy ext_proc session-affinity demonstration

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages