Forum Discussion
Frank_J_104756
Sep 24, 2007Historic F5 Account
irule feature question
Site has multiple VS, A, B, C, D...user 1 comes in and gets directed to VS A. VS A has coookie insert persistence. User gets a cookie. Something on the user side (AOL proxy) changes and user then gets directed to VS B. Can an irule be written and applied to VS A, B, C, and D that would recognize an F5 created cookie in the HTTP stream, and redirect the client back to the VS that originated the cookie ?
This is an ecommerce site and what is happening is costing a lot in money and customer satisfaction since the shopping cart doesn't stay populated.
Thanks!
16 Replies
- Deb_Allen_18Historic F5 AccountYou can also change the mask for LDNS persistence on GTM to /16, and that should keep the mega proxies from bouncing around. Of course YMMV, since all other LDNS are subject to the same grouping.
But if you have to deal with it @ LTM, assuming the pools have different names, I think you could do that with a class and an iRule cross-referencing poolname to target virtual. I'd say it would have to collect & hold the request until after the pool is selected & then decide what to do with it:class xPoolname2VSName { PoolA serverA.domain.com PoolB serverB.domain.com PoolC serverC.domain.com }when HTTP_REQUEST { set CookiePool [findstr [HTTP::cookie names] "BIGipServer" 11 " "] if { $CookiePool !=""}{ set clength [HTTP::header Content-Length] if { [HTTP::header Content-Length] > 1048576 set clength [HTTP::header Content-Length] } else { set clength 1048576 } set uri [HTTP::uri] HTTP::collect $clength } } when LB_SELECTED if { $CookiePool != "" && \ $CookiePool != [LB::server pool]}{ set VSName [findclass $CookiePool $::xPoolname2VSName " "] if $VSName != ""}{ HTTP::redirect "http://$VSName/$uri } } else { HTTP::release } [
HTH
/deb - JRahm
Admin
where is that mask setting on GTM LDNS persistence? - Frank_J_104756Historic F5 Accountdeb, I'll be keying off of cookies issued by LTM. There's a need to possible redirect to VS on another LTM. That would remove pool name as a tool for me to use. How would that change your rule. can I just look for cookie name, and redirect accordingly ?
- Deb_Allen_18Historic F5 AccountThat's pretty much what that rule does, and will still work as long as the pools have unique names across both LTMs.
In either case, the class would need to be adjusted to include IP addresses for the VS's instead of names to avoid a potential circular reference.
Because of the redirect to IP address instead of name, there are a couple of problems you might encounter with this approach:
1) clients who have been redirected will see URIs with the IP address rather than the hostname, and if those links are what they bookmark, all redundancy goes out the window.
2) some apps require an actual hostname rather than an IP address in the Host header field to function as expected (and having the IP in the Host header may aggravate issue 1, if links are relative or otherwise derived from the Host header)
I'd say you might want to push GTM persistence a bit harder...
You can set the GTM LDNS persistence mask here:
The value is the number of bits in the persistence mask.System / General Properties / Global Traffic / General / Static Persist CIDR (IPv4) or System / General Properties / Global Traffic / General / Static Persist CIDR (IPv6) - Frank_J_104756Historic F5 AccountOK dumb question then...since I know what the cookie names will be, will
if { [HTTP::cookie exists "Cookie name"]
work as well as this?when HTTP_REQUEST { set CookiePool [findstr [HTTP::cookie names] "BIGipServer" 11 " "] if { $CookiePool !=""}{ set clength [HTTP::header Content-Length] if { [HTTP::header Content-Length] > 1048576 set clength [HTTP::header Content-Length] } else { set clength 1048576 } set uri [HTTP::uri] HTTP::collect $clength } } - Deb_Allen_18Historic F5 AccountIn that example, you still would need to collect & hold the connection until a decision can be made as to its disposition.
In that example, I was parsing out the poolname from the cookie, but you could instead construct the class to contain whatever full cookie names make sense:
and then use some condition to determine the appropriate redirect. There are 2 very helpful hooks in the approach I mentioned:class xPoolname2VSIP { SiteACookieName 192.168.1.1 SiteBCookieName 192.168.2.1 }
1) since the LTM persistence cookie has nice built-in delimiters (starts with "BIGipServer", ends either with whitespace or end of string), you can isolate a unique lookup key (pool name) and look up a keyed record in the class, returning a row containing the redirect target.
and
2) you can tell immediately if the connection is on the correct VS or needs to be redirected by comparing the selected pool to the pool indicated by the cookie.
So re: 1), with the different cookie names mentioned in this new example, to take the same approach you'd need to be sure the string "Site" didn't appear anywhere else in the list of cookie names. (IOW, YMMV)
An alternative approach if you can't isolate the cookie name successfully would be to build a switch to find the right redirect.
HOWEVER...
I think in either case you run the risk of having 2 differently named persistence cookies that would match the specified pattern, and you'd only ever pick up on the first.
I think a better solution is for all servers to insert a cookie by the same name, with a unique value you can look up in the class, and include in the class the possible cookie values and the IP of the vs to which they correspond. An added bonus of this approach is that we can now redirect in the request event if the vs and cookie name don't line up, rather than collecting and waiting for a pool to be chosen:class xCookieValue2VSIP { SiteACookieValue 192.168.1.1 SiteBCookieValue 192.168.2.1 }when HTTP_REQUEST { set VSCookie [HTTP::cookie VSCookie] if { $VSCookie != ""}{ set VSIP [findclass $VSCookie $::xCookieValue2VSIP " "] compare local VS IP to the one corresponding to that cookie value & redirect if they dont' match if {$VSIP != [IP::local_addr]}{ HTTP::redirect "http://$VSIP[HTTP::uri]" } } }
HTH, and let me know if I didn't explain any of that clearly...
/deb - Frank_J_104756Historic F5 AccountI"m starting to see that my initial approach was a bit too simple then...What I'm going do to is make sure that each of the geographically distributed stand-alone LTM's have "all" pools...both the one's local to it and the pools local to the other...from what you're saying my idea of
if { [HTTP::cookie exists "Cookie name"] }{
pool poolname (where poolname is the name of the pool that was assigned to the first VS when the user was issued the cookie)
would be too simple...my thought was since the user would be in the middle of a shopping session when they changed proxies, got a new A record pointing to a new VS..I thought it'd be more complicated setting the irule up to point them back to the original VS. Plus I'd also have to change the host to map specifically to that VS - ie ww1, ww2, ww3, etc...then I'd have to use a stream profile to rewrite the generic www.sitename.com the app is giving out to ww1.sitename.com to insure the client would continue to return to that VS. As you pointed out earlier, that kind of static redirection has some flaws.
so with the scenario: user shopping off of VS1A (box 1 VS A)...then AOL switches them to another proxy which does a new lookup. Now in the middle of their shopping, with a "cart" full of items, they're redirected to VS2A (box 2 VS A). The web / app servers referenced by this VS have no knowledge of what was done on VS1A.
to get around this, my thought was, don't mess with the VS at all. If their going to bounce around between proxies that's fine...I'll use the cookie they got when they hit the VS1A initially to cause VS2A to send them to the default pool that VS1A was using. By doing this, I'd hoped to avoid them getting a new cookie, or seeing any interruption in their shopping. With that in mind, will the logic below work ? The VS would still have it's default pool so if they don't have a cookie - ie new user - then they'll get the cookie from the VS/Pool the A record sent them to and the logic would still apply...they'll continue to go to that pool
if { [HTTP::cookie exists "Cookie_for_pool_VS1A"] }{
pool VS1A
}
if { [HTTP::cookie exists "Cookie_for_pool_VS2A"] }{
pool VS2A
}
etc... - johns
Employee
There is a Static Persist CIDR setting under, "System -> Global Traffic -> General", but I do not believe there is a setting for this for Dynamic Persistence on GTM. This was one of the things that did not make during 3-DNS to GTM transition. - Frank_J_104756Historic F5 AccountDeb, you are absolutely correct. What I'm ending up with is 2 session cookies. The 1 from the original VS1A that I'm using to select the appropriate pool, plus the cookie from VS2A that I got when the new DNS A record sent me there.
- Deb_Allen_18Historic F5 AccountOK, then...
(long out of band discussion later)
Looks like we can simplify a bit.
Leave the 5 virtuals in place @ each site, each with the appropriate default pool.
Configure all 10 pools (5 local & 5 remote) on both LTMs, with exactly the same names.
Apply cookie insert persistence to all virtual servers using the default cookie name.
Then apply this rule to all the virtuals & you should be set:
/debwhen HTTP_REQUEST { set CookiePool [findstr [HTTP::cookie names] "BIGipServer" 11 " "] if { $CookiePool !=""}{ pool $CookiePool } }
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
