Avi Load Balancer includes several standard methods of persisting clients to the same server for a prolonged time.
For some applications, it may be valuable to have more customization to the persistence behaviour or to support a wider array of application types.
Persistence is based on the ability to identify a user uniquely and to stick or persist them to a destination server for a period.
The primary DataScript function for creating custom persistence is the table commands, which enable storing data locally on an Avi Load Balancer SE for a configurable time. The stored data is replicated to other relevant SEs for high availability and scale.
DataScript
Function |
Description |
---|---|
avi.vs.table_insert( [table_name,] key, value [, lifetime] ) |
Store custom data in a time-based table |
Lookup data in a table |
|
Remove data from a table |
|
avi.vs.table_refresh( [table_name,] key [, lifetime_exten] ) |
Update the expire time for a table entry |
JSessionID Example
The following example persists based upon an HTTP cookie sent from a server with a unique JSessionID. Subsequent client requests include that cookie, which is used to persist requests to the same server.
HTTP Response event: Add persist for 20 minutes, or update timer if the entry already exists
if avi.http.get_cookie("JSESSIONID") then avi.vs.table_insert(avi.http.get_cookie("JSESSIONID"), avi.pool.server_ip(), 1200) end
HTTP Request event: Rename the pool before applying to a virtual service
if avi.http.get_cookie("JSESSIONID") then avi.pool.select("poolname", avi.vs.table_lookup(avi.http.get_cookie("JSESSIONID"))) end
SSL Session ID Persistence
SSL/TLS session resumption is a mechanism to reduce the full SSL handshake between the client and server when a new connection is established. The server puts a non-zero session ID in the Server Hello, when the SSL handshake is complete. The client persists and reuses the session ID throughout the session-timeout to reduce the full SSL handshake.
Persistence is the ability to identify a session with the session ID provided by the server and to stick or persist them to a destination server for some time. Avi Load Balancer provides a way to persist session ID mapped to the server and port information using VS_DATASCRIPT_EVT_L4_REQUEST and VS_DATASCRIPT_EVT_L4_RESPONSE events.
SSL/TLS session resumption using session ID is not supported for the TLS1.3 version.
Persistence Table
The primary DataScript function for creating session ID persistence is the table commands which enable storing data locally on an Avi Load Balancer SE for a configurable length of time. The stored data is replicated to other relevant SEs for high availability and scale.
DataScripts Examples
DataScript uses the existing Default-TLS DataScript template to extract session ID from the SSL handshake. The following are the two DataScripts required for L4 persistence:
VS_DATASCRIPT_EVT_L4_REQUEST DataScript: The session ID is extracted from Client Hello. If the session ID is found, then mapped server information is found using table commands. Otherwise, it is considered as a new session.
function string.tohex(str) return (str:gsub('.', function (c) return string.format('%02X', string.byte(c)) end)) end local avi_tls = require "Default-TLS" local buffered = avi.l4.collect(10) local payload = avi.l4.read() local len = avi_tls.get_req_buffer_size(payload) if ( buffered < len ) then avi.l4.collect(100) end if ( avi_tls.sanity_check(payload) ) then local h = avi_tls.parse_record(payload) local ses = avi_tls.get_session_id(h) if ses ~= nil then persisted_info = avi.vs.table_lookup(string.tohex(ses)) if persisted_info ~= nil then sip, sport = persisted_info:match("([^,]+),([^,]+)") if(avi.pool.get_server_status("tls-pp-pool", sip, sport) ~= 1) then avi.vs.table_remove(string.tohex(ses)) else avi.pool.select("tls-pp-pool", sip, tonumber(sport)) end end avi.l4.ds_done() end end avi_tls = nil
VS_DATASCRIPT_EVT_L4_RESPONSE DataScript: The session ID is extracted from Server Hello. If the session ID is found, then the session ID and server information are inserted into the persistent table using table commands.
function string.tohex(str) return (str:gsub('.', function (c) return string.format('%02X', string.byte(c)) end)) end local avi_tls = require "Default-TLS" local buffered2 = avi.l4.collect(10) local payload2 = avi.l4.read() local len = avi_tls.get_req_buffer_size(payload2) if ( buffered2 < len ) then avi.l4.collect(100) end if ( avi_tls.sanity_check(payload2) ) then local h = avi_tls.parse_record(payload2) local ses_server = avi_tls.get_session_id(h) if ses_server ~= nil then sip, sport = avi.pool.get_server_info() avi.vs.table_insert(string.tohex(ses_server), sip..","..sport) avi.l4.ds_done() end end avi_tls = nil