diff --git a/content/en/docs/guides/ssa.md b/content/en/docs/guides/ssa.md new file mode 100644 index 0000000000..94054f1207 --- /dev/null +++ b/content/en/docs/guides/ssa.md @@ -0,0 +1,141 @@ +# Stateful Session Affinity in gRPC: A Deep Dive + +## Overview + +Stateful session affinity is a load balancing technique that ensures all RPCs +belonging to a specific session are routed to the same backend. This is achieved +by using HTTP cookies as an identifier, which the gRPC client's xDS load +balancing logic uses to consistently route RPCs to a specific backend. + +This is helpful in many cases: + +- Caching data per session: Where each backend caches data specific to a user's + session. +- Maintaining application state: Where a backend needs to maintain an active + context for a specific user session. +- Real-time interaction: For example, gaming servers where users need + to be connected to the same instance. + +## How it Works: A Step-by-Step Breakdown + +1. The first RPC in a new session does not include a session cookie. The gRPC + client uses a configured load balancing policy to select a backend to service + the RPC. Upon receiving the response, a client-side gRPC filter generates + a session cookie containing information about the selected backend (such as + base64-encoded address and cluster name). This cookie is then included in + the response metadata provided back to the user application. Users should + treat the cookie's content as an opaque implementation detail and not rely on + its specific format. +2. User code obtains the cookie from the response initial metadata. The client + application is responsible for managing and storing this cookie value, for + example, by implementing a 'cookie jar'. +3. For all subsequent RPCs that belong to the same session, the client includes + the stored cookie in the request metadata (in the cookie header). It is + the client application's responsibility to manage cookie expiration + (by checking its `Max-Age` attribute) and to avoid sending expired cookies. +4. The gRPC client's load balancing logic reads the cookie and attempts to route + the RPC to the previously identified backend using the information contained + within the cookie. + +### Behind the scenes + +The gRPC load balancing logic will prioritize sending the request to the +backend indicated by the cookie as long as it is healthy and available according +to the xDS configuration. gRPC's load balancing logic will automatically fall +back to the configured load balancing policy (e.g., round robin) to select +a new healthy backend if the backend specified in the cookie becomes unhealthy +or unreachable. The client may receive a new session cookie (generated by +the client-side filter for that new backend) upon successful connection to a new +backend - establishing affinity to the new backend. + +### Draining Backends: + +When a backend needs to be taken offline, it can enter a 'draining' state, +orchestrated via the xDS control plane. The gRPC client-side load balancer will +continue to route existing sticky sessions to the draining backend, allowing +those sessions to finish gracefully. New sessions (requests without an existing +affinity cookie) will not be routed to draining backends, enabling a controlled +shutdown. + +## Configuration +Stateful session affinity is configured through xDS. The key components of +the configuration are: + +- HttpConnectionManager: + The `HttpConnectionManager` is a core network filter within the xDS Listener + configuration that processes HTTP/2 (and HTTP/3) traffic. It includes + a `stateful_session` HTTP filter, which is responsible for managing + the cookie handling logic for SSA. +- CookieBasedSessionState: + This configuration within the `stateful_session` filter specifies: + - The cookie name. + - The cookie TTL (time to live), which corresponds to the `Max-Age` HTTP + cookie attribute. +- `override_host_status` field within the xDS Cluster configuration: + Specifies which backend health statuses are considered valid for routing for + existing sticky sessions, even if the backend is generally marked as + unhealthy for new traffic. This is essential for enabling graceful draining, + as it allows the load balancer to continue directing already-established + sessions to a backend that is in a draining state, preventing new sessions + while allowing current ones to complete. + +## xDS configuration Example +Here's an example of an LDS (Listener Discovery Service) configuration snippet. +It illustrates the HttpConnectionManager with the stateful_session HTTP filter +and its CookieBasedSessionState configuration, which are key for enabling SSA: + +```protobuf +version_info: "2" +resources { + [type.googleapis.com/envoy.config.listener.v3.Listener] { + name: "server.example.com" + api_listener { + api_listener { + [type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager] { + route_config { /* Omitted for brevity */ } + + http_filters { + name: "envoy.stateful_session" + typed_config { + [type.googleapis.com/envoy.extensions.filters.http.stateful_session.v3.StatefulSession] { + session_state { + typed_config { + [type.googleapis.com/envoy.extensions.http.stateful_session.cookie.v3.CookieBasedSessionState] { + cookie { + name: "grpc_session_cookie" + } + } + } + } + } + } + } + + http_filters { /* Omitted for brevity */ } + } + } + } + } +} +``` + +## Client-Side Implementation + +The gRPC client application needs to implement the following logic: + +- Check for the `Set-Cookie` header, which contains the session cookie generated + by the client-side gRPC SSA filter, in the response metadata when a response + is received. +- Before sending a new RPC, check if a cookie exists for the current session. + Include the cookie in the request headers using the `Cookie` header if + it exists and if it is current considering the `Max-Age` attribute value. + +## Conclusion + +Stateful session affinity is a powerful feature for gRPC applications that need +to maintain session-specific state. By leveraging HTTP cookies and +the xDS protocol, it ensures that requests belonging to a given session +are consistently routed to the same backend, leading to improved performance +(e.g., reduced latency due to caching or pre-loaded state), simplified +application logic on the backend, and enhanced reliability through graceful +backend draining. \ No newline at end of file