Forum Discussion
Alan_Sha
Nimbostratus
Oct 31, 2005How to keep the client connection when LB_FAILED?
Hi,
I need some help on the following scenario.
I have been maintaining a persistent TCP connection between a client application and Big IP. The client application is sending requests continously to Big IP while Big IP re-routes each request via iRule accordingly. Typically, the client will send one request and wait for the reply before it sends another one. However, in the event of the destination server being unreachable, I want to have Big IP drop the current package after a number of attempts to reconnect, then wait for a new one coming in and process it. I have tried to write some error handling codes in LB_FAILED event, but it appears that once I stopped calling LB::reselect in the LB_FAILED event, the client to Big IP connection will be immediately closed. That's something that I don't want to happen. I want to keep the connection alive all the time and the traffic keeps flowing.
Below is my codes for LB_FAILED event. What can I do after I stop calling LB::reselect to keep the connection and continue to process any subsequent request? Any suggestion?
when LB_FAILED {
set connRetry [expr {$connRetry + 1}]
if { $connRetry < $maxAttempts } {
log local0.error "Conn. to [IP::server_addr] failed. Retrying..."
LB::reselect
}
}
Thanks,
Alan
- unRuleY_95363Historic F5 AccountYou could either do an HTTP::respond or an HTTP::redirect.
- Alan_Sha
Nimbostratus
Thanks for the hints! Since I am dealing with a TCP socket connection instead of HTTP, I use TCP::respond instead and rerun my test.when USER_RESPONSE { if {$debug} { log local0.debug "Receive USER response ... " } LB::detach if {$debug} { log local0.debug "Detach server connection." } reset some of the flags set responsePending 0 set initResponse 1 set connRetry 0 } when LB_FAILED { set connRetry [expr {$connRetry + 1}] if { $connRetry < $maxAttempts } { log local0.error "Conn. to [IP::server_addr] failed. Retrying..." LB::reselect } else { log local0.error "Max. re-conn. attempts exhausted. Transaction dropped." TCP::respond "$::STX$::ETX" serverside {TCP::notify response} } }
- unRuleY_95363Historic F5 AccountWhat happens if you just do the LB::detach instead of issuing the "TCP::notify response"? I suspect you may be right that the original LB code isn't getting properly cleaned up. I'm thinking that you don't actually need the USER_RESPONSE event, so let's try to eliminate that first since it just adds complexity.
- Alan_Sha
Nimbostratus
I agree that we don't really need the USER_RESPONSE event. We can just perform the LB::detach in the LB_FAILED event. - unRuleY_95363Historic F5 AccountI think part of the problem might be that you need to "drop" the current package. You should be doing this with the following command:
You could probably put this right before your TCP::respond. I'm not totally sure this will get us all the way there, but you do need to remove the queue'd transaction since you are responding to it.TCP::payload replace 0 [TCP::payload length] ""
- Alan_Sha
Nimbostratus
That doesn't work either. It appears that the TCP:payload is already empty at the point the connection fails. I put some print statements to the iRule to display the [TCP::payload length] value, it shows 0. I evaluated this for both the clientside and serverside context, and both show 0. I am suspecting that once a pool statement is issued, the TCP::payload will be transferred to another internal buffer, waiting to be sent out. If this buffer is locked up or not freed for whatever reason, then any subsequent incoming request will not be able to get through because they won't be able to go into this buffer before they are forwarded to the destination. - unRuleY_95363Historic F5 AccountI'm still trying to figure out the best way to handle this. One crazy approach would be to attach to the localhost discard port and let the transaction be dumped into that. So, something like this:
when LB_FAILED { set connRetry [expr {$connRetry + 1}] if { $connRetry < $maxAttempts } { log local0.error "Conn. to [IP::server_addr] failed. Retrying..." LB::reselect } else { log local0.error "Max. re-conn. attempts exhausted. Transaction dropped." node 127.0.0.1 9 } } when SERVER_CONNECTED { if { $connRetry >= $maxAttempts } { clientside {TCP::respond "$::STX$::ETX"} LB::detach } }
- unRuleY_95363Historic F5 AccountHmm, just realized a potential problem with the above approach. We don't install inetd on the localhost. So, there's nothing listening on that particular port. Perhaps you can use the discard service on another system.
- Alan_Sha
Nimbostratus
Well, it does work. I re-routed the failed transaction to another system and let the system discard it. After that, the sub-sequent requests were able to flow without any problem. That pretty much solved the problem. - unRuleY_95363Historic F5 AccountI actually left that option out because we didn't support it - yet.
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