Weblogic Persistence done right ;=)

Problem this snippet solves:

You want to use your Weblogic issued JSESSIONID session cookie to control persistence.
A sensible option would be to employ a Cookie Hash persistence profile but then you find it to be deficient in these respects:

  • Mishandling of stale session cookies: A client making a request with a stale session cookie will cause the LTM to insert that stale session identifier into the persistence table.
  • No support for cookie-less User-Agents whereby the session id is encoded in the URL.
  • No tcl commands to query the cookie persistence table (e.g. for debug purposes).

As opposed to other Weblogic Persistence iRules found in Codeshare this irule will also allow for:

  • Minimizing the number of persistence records by persisting on the JVMID alone. That means there will be as many records as there are Weblogic Application Server instances.
  • Treating JSESSIONID value as opaque (i.e. no tolower thank you very much :)).
  • Greater control of debug logging.

How to use this snippet:

If your Virtual Server services more than one application and/or pool, don't forget to employ a one-connect profile or attach an iRule that does

LB::detach
in then response event (see SOL7964).
It is assumed pool-selection is done in a LTM Policy otherwise, if done by iRule, take care of the order of iRule execution.

Code :

# Weblogic Persist iRule, Version 0.93
# Mars, 2012
# Last update: Aug, 2012
# Updated v11.6.0: 15/02/2015

# Created by Opher Shachar (contact me through devcentral.f5.com)

# Purpose:
# This iRule persists requests based on the JSESSIONID cookie issued by the
# Weblogic server. Since Weblogic appends its JVMID to the cookie, it affords
# us the chance to persist on just the JVMID minimizig the size of the 
# persistence table.
# If not in a cookie the JSESSIONID will be searched for in the request uri.

when RULE_INIT {
   # Set debug level to: 0, 1 or 2
   set static::Weblogic_debug 1
   # Persist on JVMID only (e.g., to minimize the persist-record table)
   set static::Weblogic_JVMID 0
   # Set the name and length of the Weblogic session cookie
   set static::Weblogic_CookieName "JSESSIONID"
   set static::Weblogic_PathName   "jsessionid="
   set static::Weblogic_PathLen    [string length $static::Weblogic_PathName]
   # Set a timeout of 12 hours (43,200 seconds)
   set static::Weblogic_timeout    43200
}

when CLIENT_ACCEPTED {
   set log_prefix "Client [IP::client_addr]:[TCP::client_port]"
}

when HTTP_REQUEST {
   # Log details for the request
   if {$static::Weblogic_debug > 1} {
      log local0. "$log_prefix: Request to [HTTP::uri] with cookie: [HTTP::cookie value $static::Weblogic_CookieName]"
   }

   # Check if there is a session cookie
   set pkey [HTTP::cookie $static::Weblogic_CookieName]
   if {$pkey eq ""} {
      # Perhaps there's a jsessionid in the request uri. The jsessionid, 
      # when included is in the path: /path/to/file.ext;jsessionid=abcd!1234
      set pkey [findstr [HTTP::path] $static::Weblogic_PathName $static::Weblogic_PathLen]
   }

   # Did we find a session id?
   if {$pkey ne ""} {
      # Extract the JVMID, if none then pkey is unchanged
      set jvmid [findstr $pkey ! 1]
      if {$static::Weblogic_JVMID and ($jvmid ne "")} { set pkey $jvmid }

      # Persist off of the session id value with the set timeout
      if {[persist lookup uie $pkey] ne ""} {
         persist uie $pkey $static::Weblogic_timeout
         if {$static::Weblogic_debug > 1} {
            log local0. "$log_prefix: Used persistence record from cookie or path: [persist lookup uie $pkey]"
         }
      } else {
         # Client gave stale session id  --  don't persist
         persist none
         if {$static::Weblogic_debug > 0} {
            log local0. "$log_prefix: No persistence record found for key: $pkey"
         }
      }
   } else {
      # Client gave no session id  --  don't persist
      persist none
      if {$static::Weblogic_debug > 1} {
         log local0. "$log_prefix: No session id given in cookie or path."
      }
   }
}

when HTTP_RESPONSE {
   # Check if there is a session cookie in the response
   set pkey [HTTP::cookie $static::Weblogic_CookieName]
   if {$pkey eq "" and [HTTP::is_redirect]} {
      # Perhaps there's a jsessionid in the redirect uri. The jsessionid, 
      # when included is in the path: /path/to/file.ext;jsessionid=abcd!1234
      set pkey [findstr [URI::basename "[HTTP::header Location]"] $static::Weblogic_PathName $static::Weblogic_PathLen]
   }

   # Did we find a session id?
   if {$pkey ne ""} {
      # Extract the JVMID, if none then pkey is unchanged
      set jvmid [findstr $pkey ! 1]
      if {$static::Weblogic_JVMID and ($jvmid ne "")} { set pkey $jvmid }

      # Persist the session id value with the set timeout
      persist add uie $pkey $static::Weblogic_timeout
      if {$static::Weblogic_debug > 0} {
         set val [persist lookup uie $pkey]
         log local0. "$log_prefix: Added persistence record from cookie or redirect: $pkey -> $val"
      }
   }
}

Tested this on version:

11.4
Updated Jun 06, 2023
Version 2.0
No CommentsBe the first to comment