Forum Discussion
Erki_Märks_2779
Nimbostratus
Nov 29, 2007Bea Weblogic persistence
We are using bigip with Weblogic cluster. Since session is replicated only on 2 nodes, we had to find a solution that knew the additional server where the original session was replicated and if the primary node was down the irule had to switch over to the second node. I finally found a solotion that seems to work.
Any ideas how to improve/change it?
when RULE_INIT {
array set ::nodelist { }
array unset ::nodelist
}
when CLIENT_ACCEPTED {
set insert_wls_headers 1
set reselect 0
set retries 0
set node1 ""
set node2 ""
set lastServer ""
}
when HTTP_REQUEST {
set request [HTTP::request]
set uri [HTTP::uri]
set hostname [HTTP::header host]
if { $insert_wls_headers } {
HTTP::header insert WL-Proxy-SSL false
HTTP::header insert WL-PATH-PREPEND test
HTTP::header insert WL-Proxy-Client-IP [IP::client_addr]
HTTP::header insert Proxy-Client-IP [IP::client_addr]
HTTP::header insert X-WebLogic-Request-ClusterInfo true
set insert_wls_headers 0
}
switch -regexp $uri {
mainservlet {
set jss [findstr [HTTP::uri] "jsessionid" 11 "?"]
set jsess [getfield $jss "!" 1]
set jvmid1 [getfield $jss "!" 2]
set jvmid2 [getfield $jss "!" 3]
if { [ info exists ::nodelist($jvmid1) ] } {
set node1 $::nodelist($jvmid1)
}
if { [ info exists ::nodelist($jvmid2) ] } {
set node2 $::nodelist($jvmid2)
}
if { "$node1" != "" &&
[LB::status pool prelive_wls_pool member $node1 7001] != "down" &&
"$lastServer" != "$node1" && $reselect < 2 && $retries < 2 } {
pool prelive_wls_pool member $node1 7001
} elseif { "$node2" != "" &&
[LB::status pool prelive_wls_pool member $node2 7001] != "down" &&
"$lastServer" != "$node2" && $reselect < 2 && $retries < 2 } {
pool prelive_wls_pool member $node2 7001
} else {
pool prelive_wls_pool
} default {
pool prelive_wls_static_pool
}
}
}
when LB_FAILED {
LB::down
if { [matchclass $uri starts_with $::servlets] } {
set lastServer [LB::server addr]
incr reselect
if { [LB::server addr] == "" || $reselect > [active_members prelive_wls_pool ] } {
reject
return
} else {
LB::reselect pool prelive_wls_pool
if { "$lastServer" == "$node1" && "$node2" != "" && $reselect < 2 &&
[LB::status pool prelive_wls_pool member $node2 7001] != "down" } {
pool [LB::server pool] member $node2 7001
} elseif { "$lastServer" == "$node2" && "$node1" != "" && $reselect < 2 &&
[LB::status pool prelive_wls_pool member $node1 7001] != "down" } {
pool [LB::server pool] member $node1 7001
}
}
}
}
when HTTP_RESPONSE {
if { [HTTP::header exists "X-WebLogic-Cluster-List"] }{
set server_mappings [split [HTTP::header "X-WebLogic-Cluster-List"] "|" ]
HTTP::header remove "X-WebLogic-Cluster-List"
foreach servermap $server_mappings {
set jvmid [getfield $servermap "!" 1]
set ipp [getfield $servermap "!" 2]
set ip1 [expr {($ipp >> 24) & 0xff}]
set ip2 [expr {($ipp >> 16) & 0xff}]
set ip3 [expr {($ipp >> 8) & 0xff}]
set ip4 [expr {$ipp & 0xff}]
if { [ info exists ::nodelist($jvmid) ] } {
log "jvmid: $jvmid; ip: $ip1.$ip2.$ip3.$ip4"
} else {
set ::nodelist([getfield $servermap "!" 1]) "$ip1.$ip2.$ip3.$ip4"
log "jvmid: $jvmid; ip: $ip1.$ip2.$ip3.$ip4"
}
}
}
if { [matchclass $uri starts_with $::servlets] } {
set lastServer [LB::server addr]
switch -regexp [HTTP::status] {
50[0-3]$ {
LB::down
LB::detach
incr retries
if {$retries < 3 && [ info exists ::nodelist($jvmid2) ] } {
log "WARNING: $host retrying $retries"
HTTP::retry $request
}
}
}
}
}
6 Replies
- Erki_Märks_2779
Nimbostratus
If LB_FAILED or http errors direct the user to the mainservlet :
else {
if { $reselect > 1 || $retries > 1 } {
HTTP::uri "/test/mainservlet"
}
pool prelive_wls_pool
} - Erki_Märks_2779
Nimbostratus
Yes, but with regex its simple, for example:
^/(files|lib|js|img|test|..)/(?!(.*)(servlet1|servlet2).*$) {
pool1
} default {
pool2
} - Erki_Märks_2779
Nimbostratus
This irule should work fine, tested with wl8
when RULE_INIT {
array set ::nodelist { }
array unset ::nodelist
}
when CLIENT_ACCEPTED {
set insert_wls_headers 1
set reselect 0
set retries 0
set node1 ""
set node2 ""
set lastServer ""
}
when HTTP_REQUEST {
set request [HTTP::request]
set uri [HTTP::uri]
set hostname [HTTP::header host]
if { $insert_wls_headers } {
HTTP::header insert WL-Proxy-SSL false
HTTP::header insert WL-PATH-PREPEND test
HTTP::header insert WL-Proxy-Client-IP [IP::client_addr]
HTTP::header insert Proxy-Client-IP [IP::client_addr]
HTTP::header insert X-WebLogic-Request-ClusterInfo true
set insert_wls_headers 0
}
switch -regexp $uri {
mainservlet {
set jss [findstr [HTTP::uri] "jsessionid" 11 "?"]
set jsess [getfield $jss "!" 1]
set jvmid1 [getfield $jss "!" 2]
set jvmid2 [getfield $jss "!" 3]
if { [ info exists ::nodelist($jvmid1) ] } {
set node1 $::nodelist($jvmid1)
}elseif { [ info exists ::nodelist($jvmid2) ] } {
set node2 $::nodelist($jvmid2)
}
if { "$node1" != "" &&
[LB::status pool prelive_wls_pool member $node1 7001] != "down" &&
"$lastServer" != "$node1" && $reselect < 2 && $retries < 2 } {
pool prelive_wls_pool member $node1 7001
} elseif { "$node2" != "" &&
[LB::status pool prelive_wls_pool member $node2 7001] != "down" &&
"$lastServer" != "$node2" && $reselect < 2 && $retries < 2 } {
pool prelive_wls_pool member $node2 7001
} else {
pool prelive_wls_pool
} default {
pool prelive_wls_static_pool
}
}
}
when LB_FAILED {
LB::down
if { [matchclass $uri starts_with $::servlets] } {
set lastServer [LB::server addr]
incr reselect
if { [LB::server addr] == "" || $reselect > [active_members prelive_wls_pool ] } {
reject
return
} else {
LB::reselect pool prelive_wls_pool
if { "$lastServer" == "$node1" && "$node2" != "" && $reselect < 2 &&
[LB::status pool prelive_wls_pool member $node2 7001] != "down" } {
pool [LB::server pool] member $node2 7001
} elseif { "$lastServer" == "$node2" && "$node1" != "" && $reselect < 2 &&
[LB::status pool prelive_wls_pool member $node1 7001] != "down" } {
pool [LB::server pool] member $node1 7001
}
}
}
}
when HTTP_RESPONSE {
if { [HTTP::header exists "X-WebLogic-Cluster-List"] }{
set server_mappings [split [HTTP::header "X-WebLogic-Cluster-List"] "|" ]
HTTP::header remove "X-WebLogic-Cluster-List"
foreach servermap $server_mappings {
set jvmid [getfield $servermap "!" 1]
set ipp [getfield $servermap "!" 2]
set ip1 [expr {($ipp >> 24) & 0xff}]
set ip2 [expr {($ipp >> 16) & 0xff}]
set ip3 [expr {($ipp >> 8) & 0xff}]
set ip4 [expr {$ipp & 0xff}]
if { [ info exists ::nodelist($jvmid) ] } {
log "jvmid: $jvmid; ip: $ip1.$ip2.$ip3.$ip4"
} else {
set ::nodelist([getfield $servermap "!" 1]) "$ip1.$ip2.$ip3.$ip4"
log "jvmid: $jvmid; ip: $ip1.$ip2.$ip3.$ip4"
}
}
}
if { [matchclass $uri starts_with $::servlets] } {
set lastServer [LB::server addr]
switch -regexp [HTTP::status] {
5 0 [ 0 - 3 ]$ {
LB::down
LB::detach
incr retries
if {$retries < 3 && [ info exists ::nodelist($jvmid2) ] } {
log "WARNING: $host retrying $retries"
HTTP::retry $request
}
}
}
}
} - Deb_Allen_18Historic F5 Accountnice, thanks for the post.
I've been noodling with this idea off & on for the last year without an environment to test in, looks like you may have nailed it.
Regarding optimization:
You probably want to take a look at this article Colin recently wrote about polymorphic operators (Click here) and replace some of them with the appropriate string operators where ever string-only comparisons take place.
And I agree with Colin on eliminating the regex ops as much as possible. While it seems like a trivial choice, (especially if you are as comfortable with regex as you obviously are), the cost of firing up the regex engine is apparently obscenely expensive in comparison with the alternatives, especially the iRules native comparison operators, so you might consider using them in place of your 2 "switch -regex's"
I'd replace:
withswitch -regexp $uri { mainservlet {
only if you need to match multiple URI's.switch -glob $uri { *mainservlet* {
Otherwise use the even more efficient
for a single test like this.if { $uri contains "mainservlet"} {
I'd also replace:
withswitch -regexp [HTTP::status] { 50[0-3]$ {if { [HTTP::status] starts_with "50"} {
HTH
/deb - Deb_Allen_18Historic F5 Accountcorrected some syntax, but still looks like
5 0 [ 0 - 3 ]
(less the spaces)
Is being replaced with
(less the spaces)5 0 Ύ - 3 ]
/deb - Dmitriy_Sysoev
Nimbostratus
Hello? If exist node3 ?
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
