Forum Discussion
1 VS, 2 pool routing requirements...help?
I have the following iRule. It's working as needed. It might be clumbsy, but it works. (thoughts on a cleaner implementation?).
It chooses a pool based on a cookie, or a response from the server in the pool it it hit the wrong pool.
What I need...is to add more pool-selection logic to it to choose a pool (after determining which client it is) based on URI in order to separate some apps from the rest due to performance/capacity concerns.
Thoughts on how I can accoplish this in the most effective/maintainable way?
I hope copy/paste looks ok, not sure how to paste 'code' and make it look pretty here:
set iRule priority higher than the default to better it's functionality
priority 300
when HTTP_REQUEST {
Look for existing pool cookie otherwise determine where to go based on
a lookup of client IP in the Client 'proxy' Server addresses datalist
set to 1 to enable LTM logging, 0 to disable LTM logging
set debugWPPBF 0
init flag whether to run iRule or just exit
set ShouldExitWPPBF 0
if {[string tolower [HTTP::path]] starts_with "/streamer"} {
stop running the iRule since PERSIST profile will pick up /streamer calls
set ShouldExitWPPBF 1
return
}
if {$debugWPPBF}{log local0.info "Cookie TFPoolId Exists: [HTTP::cookie exists "TFPoolId"]"}
if {[HTTP::cookie exists "TFPoolId"] && ![info exists retriesWPPBF]} {
Pool cookie exists...just send the request
switch [HTTP::cookie "TFPoolId"] {
"1" { set PoolIdWPPBF "BLTCP_WEB" }
"2" { set PoolIdWPPBF "WSI_WEB" }
default { set PoolIdWPPBF "BLTCP_WEB" }
}
pool $PoolIdWPPBF
if {$debugWPPBF}{log local0.info "Cookie Pooling [IP::client_addr] to $PoolIdWPPBF"}
} else {
no pool cookie so we need to determine where to go
if { [info exists retriesWPPBF] } {
We are in retry so just send it to the new pool
if {$debugWPPBF}{log local0.info "isRetry to $NewPoolIdWPPBF"}
Update content length header with updated payload length
HTTP::header replace Content-Length [string length [HTTP::payload]]
pool $NewPoolIdWPPBF
} else {
we have no pool cookie and are in the 1st request...get setup to determine if we need to retry to a new pool
if {$debugWPPBF}{log local0.info "No Cookie"}
set noCookie 1
Set request, HTTP post header.
set requestWPPBF [HTTP::request]
if {$debugWPPBF}{log local0.info "HTTP::request: $requestWPPBF"}
Set payload content legth to capture.
if {[HTTP::header exists "Content-Length"] && [HTTP::header "Content-Length"] <= 4000000}{
set content_lengthWPPBF [HTTP::header "Content-Length"]
} else {
set content_lengthWPPBF 4000000
}
Capture HTTP payload from request, HTTP::collect triggers event HTTP_REQUEST_DATA
if { [info exists content_lengthWPPBF] && $content_lengthWPPBF > 0} {
if {$debugWPPBF}{log local0.info "Collecting Payload"}
HTTP::collect $content_lengthWPPBF
}
set PoolIdWPPBF ""
set isMatchWPPBF [class match [IP::client_addr] equals WFAPriceServerList]
if {$debugWPPBF}{log local0.info "Returned '$isMatchWPPBF' from WFA price server lookup"}
if {$isMatchWPPBF} {
pool WSI_WEB
if {$debugWPPBF}{log local0.info "Pooling to WSI_WEB"}
} else {
pool BLTCP_WEB
if {$debugWPPBF}{log local0.info "Pooling to BLTCP_WEB"}
}
}
}
}
when HTTP_REQUEST_DATA {
Set payload, depends on HTTP::collect done in HTTP_REQUEST event.
set payloadWPPBF [HTTP::payload]
Append HTTP payload to HTTP request header to form a complete HTTP post request (request + payload)
append requestWPPBF [HTTP::payload [HTTP::payload length]]
Log payload
if {$debugWPPBF} { log local0.info "Payload: $payloadWPPBF - length: [HTTP::payload length]" }
}
when HTTP_RESPONSE {
Watch for a response status of 307 from a misdirected pool
and change the cookie value accordingly
otherwise set the cookie to the selected pool
if {$ShouldExitWPPBF} { return }
if {$debugWPPBF}{log local0.info "status: '[HTTP::status]' - header: '[HTTP::header "WMErrorID"]'"}
if {[HTTP::status] eq "307" && [HTTP::header "WMErrorID"] eq "307" } {
HTTP::cookie remove "TFPoolId"
if {[HTTP::header value "FirmRoute"] eq 901} {
set NewCookieValueWPPBF "2"
HTTP::cookie insert name "TFPoolId" value $NewCookieValueWPPBF path "/"
set NewPoolIdWPPBF "WSI_WEB"
if {$debugWPPBF}{log local0.info "Wrong Pool, Changing to WSI_WEB"}
} else {
set NewCookieValueWPPBF "1"
HTTP::cookie insert name "TFPoolId" value $NewCookieValueWPPBF path "/"
set NewPoolIdWPPBF "BLTCP_WEB"
if {$debugWPPBF}{log local0.info "Wrong Pool, Changing to BLTCP_WEB"}
}
if { ![info exists retriesWPPBF] } {
Set retries to activate the retry logic
set retriesWPPBF 1
Retry HTTP request/payload to another pool.
if {[info exists requestWPPBF] && $requestWPPBF ne ""} {
if {$debugWPPBF}{log local0.info "Retrying: $requestWPPBF"}
HTTP::retry "$requestWPPBF"
return
} else {
if {$debugWPPBF}{log local0.info "No collected request - responding to client"}
HTTP::cookie remove "TFPoolId"
}
}
} else {
if {$debugWPPBF}{log local0.info "PoolIdWPPBF: $PoolIdWPPBF"}
if {[info exists noCookie] || [info exists retriesWPPBF]} {
switch [LB::server pool] {
"BLTCP_WEB" { HTTP::cookie insert name "TFPoolId" value "1" path "/" }
"WSI_WEB" { HTTP::cookie insert name "TFPoolId" value "2" path "/" }
default { HTTP::cookie insert name "TFPoolId" value "1" path "/" }
}
Update content length header with updated payload length
REMOVED HTTP::header replace Content-Length [string length [HTTP::payload]]
if {$debugWPPBF}{log local0.info "No 307, Setting Cookie for [LB::server pool] - Client: [IP::client_addr]"}
if {[info exists noCookie]}{ unset noCookie }
}
if {[info exists retriesWPPBF]}{
if {$debugWPPBF}{log local0.info "unsetting retriesWPPBF"}
unset retriesWPPBF
}
}
Insert header with responding server IP
HTTP::header replace "serverIP" [IP::server_addr]
}
when LB_SELECTED {
if {$ShouldExitWPPBF} { return }
if { [info exists retriesWPPBF] } {
if {$debugWPPBF}{log local0.info "Redirecting Request to $NewPoolIdWPPBF - member: [LB::server]"}
LB::reselect pool $NewPoolIdWPPBF
}
}
- nitass
Employee
what about if we create another HTTP_REQUEST event with higher priority and disable all event when the condition matches? - Jason_Hook_4092
Nimbostratus
We have an n-tier application architecture. The web tier/pools are the entry point to the environment. The catch is that we have 2 production environments that reside behind the same VIP. Currently, one pool of web servers (PoolId=1) is for our web products as a service bureau offering...and the other pool (PoolId=2) is for one specific client that requires us to have a separate set of servers (pretty much a mirror of the architecture that is behind PoolId=1) so there is impact isolation (they are paying to have their own in order to not be impacted if another of our clients add load in the environment that slows it down).
- Jason_Hook_4092
Nimbostratus
Does anyone have any suggestions?
Recent Discussions
Related Content
* 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