Uploaded image for project: 'WildFly'
  1. WildFly
  2. WFLY-16043

Allow configuration of an arbitrary cookie to use for web request affinity

XMLWordPrintable

      Currently, WildFly only supports the ability to encode session affinity information into the JSESSIONID cookie, which is already used to uniquely identify a session.  This plays nicely with the httpd family of load balancer modules (e.g. mod_cluster, mod_proxy_balancer, mod_jk) for which this mechanism was designed.

      However, many load balancers rely on a separate cookie for implementing sticky sessions (e.g. HAProxy, IIS, etc.), and thus lack the ability to allow WildFly to guide requests for a given session to the server that can most efficiently handle it.

      To resolve this, we should add a configuration attribute within the Undertow subsystem to allow the use of a configurable cookie to store session affinity information.

      e.g.

      <servlet-container name="...">
         <session-cookie name="JSESSIONID" affinity-cookie-name="ARR" .../>
      </servlet>
      

      If undefined, the route will be encoded into the session identifier via the existing CodecSessionConfig SessionConfig decorator.

      If defined, we create a separate SessionConfig implementation for the route cookie (a copy of the session's SessionConfig, but with a distinct cookie name). We can then implement session affinity via a SessionConfig decorator. This decorator should be compatible with any future SessionConfig implementations we decide to support in WildFly (e.g. SSL, path parameters, etc.).
      e.g.

      public class AffinitySessionConfig implements SessionConfig {
      
          private final SessionConfig sessionConfig;
          private final SessionConfig routeConfig;
          private final RouteLocator locator;
      
          public AffinitySessionConfig(SessionConfig sessionConfig, SessionConfig routeConfig, RouteLocator locator) {
              this.sessionConfig = sessionConfig;
              this.routeConfig = routeConfig;
              this.locator = locator;
          }
      
          @Override
          public void setSessionId(HttpServerExchange exchange, String sessionId) {
              String existingSessionId = this.sessionConfig.findSessionId(exchange);
              if (!sessionId.equals(existingSessionId)) {
                  this.sessionConfig.setSessionId(exchange, sessionId);
              }
              String route = this.locator.locate(sessionId);
              if (route != null) {
                  String existingRoute = this.routeConfig.findSessionId(exchange);
                  if (!route.equals(existingRoute)) {
                      this.routeConfig.setSessionId(exchange, route);
                  }
              }
          }
      
          @Override
          public void clearSession(HttpServerExchange exchange, String sessionId) {
              this.sessionConfig.clearSession(exchange, sessionId);
              String existingRoute = this.routeConfig.findSessionId(exchange);
              if (existingRoute != null) {
                  this.routeConfig.clearSession(exchange, existingRoute);
              }
          }
      
          @Override
          public String findSessionId(HttpServerExchange exchange) {
              return this.sessionConfig.findSessionId(exchange);
          }
      
          @Override
          public SessionCookieSource sessionCookieSource(HttpServerExchange exchange) {
              return this.sessionConfig.sessionCookieSource(exchange);
          }
      
          @Override
          public String rewriteUrl(String originalUrl, String sessionId) {
              String url = this.sessionConfig.rewriteUrl(originalUrl, sessionId);
              String route = this.locator.locate(sessionId);
              return (route != null) ? this.routeConfig.rewriteUrl(url, route) : url;
          }
      }
      

       

              rhn-engineering-rhusar Radoslav Husar
              pferraro@redhat.com Paul Ferraro
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated:
                Resolved: