Consistent hashing
Set up soft session affinity between a client and an upstream service by using consistent hashing algorithms.
About session affinity
Session affinity, also referred to as sticky session, allows you to route requests for a particular session to the same upstream service instance that served the initial request. This setup is particularly useful if you have an upstream service that performs expensive operations and caches the output or data for subsequent requests. With session affinity, you make sure that the expensive operation is performed once and that subsequent requests can be served from the upstream’s cache, which can significantly improve operational cost and response times for your clients.
About consistent hashing
Gloo Gateway allows you to set up soft session affinity between a client and an upstream service by using the Ringhash or Maglev consistent hashing algorithm. The hashing algorithm uses a property of the request, such as a header, and hashes this property with the address of an upstream service instance that served the initial request. In subsequent requests, as long as the client sends the same header, the request is routed to the same upstream service instance.
Consistent hashing is less reliable than a common sticky session implementation, in which the upstream service is encoded in a cookie and affinity can be maintained for as long as the upstream service is available. With consistent hashing, affinity might be lost when an upstream service is added or removed. To set up strong stickiness, see the Stateful session filter docs.
Before you begin
Follow the Get started guide to install Gloo Gateway, set up a gateway resource, and deploy the httpbin sample app.
Get the external address of the gateway and save it in an environment variable.
Set up Ringhash and Maglev hashing
Scale the httpbin app up to 2 instances.
kubectl scale deployment httpbin -n httpbin --replicas=2
Verify that another instance of the httpbin app is created and note the IP addresses of both httpbin instances. In the following example, you have an httpbin instance available at the
10.0.43.175
and10.0.38.52
IP addresses.kubectl get pods -n httpbin -o wide
Example output
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpbin-8d557795f-86hzg 3/3 Running 0 54m 10.0.43.175 ip-10-0-34-108.ec2.internal <none> <none> httpbin-8d557795f-h8ks9 3/3 Running 0 126m 10.0.38.52 ip-10-0-39-74.ec2.internal <none> <none>
Create an Upstream for the httpbin app. An Upstream is required to later configure the Ringhash or Maglev hashing algorithm.
kubectl apply -f- <<EOF apiVersion: gloo.solo.io/v1 kind: Upstream metadata: name: httpbin namespace: gloo-system spec: kube: serviceName: httpbin serviceNamespace: httpbin servicePort: 8000 EOF
Create an HTTPRoute that routes requests on the
httpbin.example
domain to the httpbin Upstream.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httpbin-upstream namespace: gloo-system spec: parentRefs: - name: http namespace: gloo-system hostnames: - httpbin.example rules: - backendRefs: - name: httpbin kind: Upstream group: gloo.solo.io EOF
Send a request to the
httpbin.example
domain and verify that you can route traffic to the httpbin Upstream.Example output:
HTTP/1.1 200 OK access-control-allow-credentials: true access-control-allow-origin: * content-type: application/json; encoding=utf-8 date: Wed, 05 Mar 2025 20:42:32 GMT x-envoy-upstream-service-time: 1 server: envoy transfer-encoding: chunked
Update the httpbin Upstream to configure a Ringhash or Maglev hashing algorithm for the Upstream.
Create a RouteOption to store the hashed value in the
hashbasedcookie
cookie. The cookie is valid for 60 seconds. The RouteOption is applied to thehttpbin-upstream
HTTPRoute that you created earlier.kubectl apply -f- <<EOF apiVersion: gateway.solo.io/v1 kind: RouteOption metadata: name: lbhash namespace: gloo-system spec: targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: httpbin-upstream options: lbHash: hashPolicies: - cookie: name: hashbasedcookie ttl: 60s path: / EOF
Send a request to the httpbin app and verify that you see the
hashbasedcookie
cookie in theset-cookie
header of your response. The-c
option stores the cookie in a local file on your machine so that you can use it in subsequent requests.Example output:
< set-cookie: hashbasedcookie="298b1ac340fdea97"; Max-Age=60; Path=/; HttpOnly set-cookie: hashbasedcookie="298b1ac340fdea97"; Max-Age=60; Path=/; HttpOnly < server: envoy server: envoy < { "headers": { "Accept": [ "*/*" ], "Host": [ "httpbin.example:8080" ], "User-Agent": [ "curl/8.7.1" ], "X-Envoy-Expected-Rq-Timeout-Ms": [ "15000" ], "X-Forwarded-Proto": [ "http" ], "X-Request-Id": [ "fe080d74-2b6e-4954-8bde-54bed3e71dde" ] } }
Repeat the request a few more times. Include the cookie that you stored in the local file by using the
-b
option. Make sure to send these requests within the 60 second cookie validity period.Get the logs of the httpbin instance that served the initial request. Verify that all subsequent requests were also served by the same instance.
kubectl logs <httpbin-pod> -n httpbin
After the cookie reaches its TTL (time to live) and expires, the proxy starts choosing a new upstream instance to serve the request.
Cleanup
You can optionally remove the resources that you created in this guide.
kubectl delete routeoption lbhash -n gloo-system
kubectl delete httproute httpbin-upstream -n gloo-system
kubectl delete upstream httpbin -n gloo-system
kubectl scale deployment httpbin -n httpbin --replicas=1