Forum Discussion
Tuomas_Jormola_
Nimbostratus
Apr 17, 2008Strange things happening while attempting universal persistence using JSESSIONID
Hi,
I'm setting up a Java web application behind a pair of F5 BIG-IP LTMs
running operating system version 9.3.1. The application is hosted on
a cluster of machines running Resin servlet container.
The backend nodes are not using any kind of shared session store,
so we need to direct each session to the same backend node that
served the initial request. Resin is configured to use JSESSIONID cookie
to store the session identifier. So based on documentation and
examples found here on DevCentral, I created a universal persistence
profile, and assigned that to the virtual server as the only
persistency profile. The iRule powering the profile is included below
(it also supports setting the session id in the request URI,
but cookies are preferred).
when RULE_INIT {
set ::debug 1
}
when CLIENT_ACCEPTED {
if { $::debug } {
set client [IP::client_addr]:[TCP::client_port]
}
}
when HTTP_RESPONSE {
if { [HTTP::cookie exists "JSESSIONID"] } {
set jsessionid [HTTP::cookie "JSESSIONID"]
persist add uie $jsessionid 3600
if { $::debug } {
log local0. "NEW PERSIST ENTRY client>$client< JSESSIONID>$jsessionid<"
}
}
}
when HTTP_REQUEST {
set jsessionid ""
set cookie_id ""
set uri [HTTP::uri]
set uri_id [findstr $uri "jsessionid=" 11 "?"]
if { [HTTP::cookie exists "JSESSIONID"] } {
set cookie_id [HTTP::cookie "JSESSIONID"]
}
if { $cookie_id ne "" } {
set jsessionid $cookie_id
} elseif { $uri_id ne "" } {
set jsessionid $uri_id
}
if { $jsessionid ne "" } {
persist uie $jsessionid 3600
}
if { $::debug } {
set table ""
if { $jsessionid ne "" } {
set table [persist lookup uie $jsessionid]
}
if { $table eq "" } {
log local0. "client>$client< uri>$uri< cookie_id>$cookie_id< uri_id>$uri_id< JSESSIONID>$jsessionid< table>null<"
} else {
log local0. "client>$client< uri>$uri< cookie_id>$cookie_id< uri_id>$uri_id< JSESSIONID>$jsessionid< table>[lindex $table 0] [lindex $table 1] [lindex $table 2]<"
}
}
}
when LB_SELECTED {
if { $::debug } {
set server [LB::server addr]:[LB::server port]
log local0. "client>$client< server>$server<"
}
}
when LB_FAILED {
if { $::debug } {
if { $jsessionid ne "" } {
if { $table ne "" } {
log local0. "client>$client< JSESSIONID>$jsessionid< table>[lindex $table 0] [lindex $table 1] [lindex $table 2]<"
} else {
log local0. "client>$client< JSESSIONID>$jsessionid< table>null<"
}
} else {
log local0. "client>$client< JSESSIONID>null< table>null<"
}
}
if { $jsessionid ne "" } { persist delete uie $jsessionid }
if { $table ne "" } { LB::reselect pool [lindex $table 0] }
}
However, when this setup is in place, we noticed that requests of
a session were not actually always directed to the same node,
even though the logic seemed to work as sane values were printed in
the syslog by iRule debugging statements. I give an example using
the debug statements in the iRule and HTTP data captured using tcpdump
on the BIG-IP LTM when the web application was accessed with a browser.
Setup:
Client IP: 194.137.112.98
BE Nodes: 192.168.135.16:6889 and 192.168.135.17:6889
Here we have the first request from the client
(irrelevant HTTP headers omitted)
GET /littleredcap-demo/app/?lang=fi HTTP/1.1
As you can see, we have no session cookie.
The request was served by 192.168.135.17 with response
HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=abccmG4bh7OVaeO7KjCLr; path=/
We now have the cookie. Corresponding debug log entries from the iRule:
Apr 17 14:30:24 tmm tmm[875]: Rule persist_jsessionid : client>194.137.112.98:8283< uri>/littleredcap-demo/app/?lang=fi< cookie_id>< uri_id>< JSESSIONID>< table>null<
Apr 17 14:30:24 tmm tmm[875]: Rule persist_jsessionid : client>194.137.112.98:8283< server>192.168.135.17:6998<
Apr 17 14:30:25 tmm tmm[875]: Rule persist_jsessionid : NEW PERSIST ENTRY client>194.137.112.98:8283< JSESSIONID>abccmG4bh7OVaeO7KjCLr<
So the iRule logs that new universal persistence entry has been created
for this session id, and we're using 192.168.135.17:6998 as
the backend node for the session.
But then, with next request hitting the virtual server, things are
getting weird. The request that the browser sends in order to get some
CSS resource needed to render the front page looks like this.
GET /littleredcap-demo/css/app-layout.css HTTP/1.1
Cookie: JSESSIONID=abccmG4bh7OVaeO7KjCLr
We have the session id, as iRule log entry confirms
Apr 17 14:30:25 tmm tmm[875]: Rule persist_jsessionid : client>194.137.112.98:8276< uri>/littleredcap-demo/css/app-layout.css< cookie_id>abccmG4bh7OVaeO7KjCLr< uri_id>< JSESSIONID>abccmG4bh7OVaeO7KjCLr< table>test_pool 192.168.135.17 6998<
This log entry finds the original backend node associated for
the session, 192.168.135.17. But the tcpdump capture and access log
on the backend 192.168.135.16 revealed that the actual request was
redirected to the node 192.168.135.16 instead! So persistency for
this esablished session was not honoured, and the default
scheduling algorithm that chooses the node from the pool was
applied instead.
Any idea why this happened? Can someone point out the flaw in
the iRule? Thanks.
10 Replies
- Kevin_Stewart
Employee
I may be missing something in your explanation, but is there a specific reason that you cannot use the BigIP builtin cookie persistence mechanism? With this the BigIP sends its own cookie to the client that indicates the LB node. - Nicolas_Menant
Employee
Just one question: are you using oneconnect ? - Tuomas_Jormola_
Nimbostratus
Posted By nmenant on 04/17/2008 7:10 AM
- Tuomas_Jormola_
Nimbostratus
Hi,Posted By kevin.stewart on 04/17/2008 6:44 AM
- Tuomas_Jormola_
Nimbostratus
Looks like adding a OneConnect profile with mask 255.255.255.255 to the virtual server solved the problem. - Nicolas_Menant
Employee
Glad it works with oneconnect."When a OneConnect profile is enabled for a virtual server, and an HTTP client sends multiple requests within a single connection, the BIG-IP LTM is able to process each HTTP request individually. The BIG-IP LTM sends the HTTP requests to different destination servers if necessary. Without a OneConnect profile enabled for the virtual server, the BIG-IP system performs load-balancing for each TCP connection."
- Andy_Herrman_22
Nimbostratus
Sounds like you got it working, but I think I saw a bug in your iRule that could cause some problems later on.set uri_id [findstr $uri "jsessionid=" 11 "?"]
- hoolio
Cirrostratus
aherrman, - Tuomas_Jormola_
Nimbostratus
Posted By hoolio on 04/25/2008 12:58 AM
- dimka___104021
Nimbostratus
Hi,
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects