Forum Discussion
Respond with cached content after timeout
As commented in the explanation for the "after" command (https://devcentral.f5.com/wiki/iRules.after.ashx) we can make some actions with the http request. It's possible to respond with cached content if web acceleration application is also configured with stand-in period codes? Something like that:
when RULE_INIT {
set static::response_timeout 15000
}
when HTTP_REQUEST {
set monitor_id [\
after $static::response_timeout {
Respond with cached content
}\
]
}
when HTTP_RESPONSE {
log local0. "Received server response. "
if {[info exists monitor_id]} {
log local0. "Canceling after script with id $monitor_id"
after cancel $monitor_id
}
Thanks in advance.
- IheartF5_45022Nacreous
Hi yes you can do this but it's quite complicated unfortunately. You'll need to setup 2 virtual servers, vs_webapp, and vs_webapp_backend (the 2nd one needs to have the same name as the first one, but with '_backend' appended). The config of the 2 can be identical with the exception of the iRles (below) attached. In addition only vs_webapp needs to be enabled on the ingress VLAN.
vs_webapp has the following iRule attached;-
when RULE_INIT { The wait interval in ms set static::wait_ms 200 The low watermark for wait iterations - used for conditional GETs where stale content exists in WAM - when set low will result in more requests being served stale content Use 0 here to achieve "serve stale on expiration" behaviour set static::low_loop_cnt 20 The high watermark for wait iterations - used for non-conditional GETs where no stale content exists in WAM - this must be hi gher than $low_loop_cnt when set too low will result in many concurrent requests being sent to OWS and if set too high may result in too many requests queued concurrently would suggest 60<=high_loop_cnt<=300 but depends on the application and baseline testing of that. set static::high_loop_cnt 240 } when HTTP_REQUEST { set debug 0 log prefix for connection/request tracking. All debug logs will start with [xxxx.yyyy] where xxxx is the connection and yyyy is the request id if {$debug} { per request identifier set prefix "\[[expr {int (rand() * 10000)}]\] " this notifies backend VIP we are in debug mode and passes the connection prefix. HTTP::header replace "X-tls-debug" $prefix } set table "[getfield [HTTP::host] : 1][string tolower [URI::decode [HTTP::path]]]" if {$debug} {log local0. "${prefix}$table [clock clicks -milliseconds]"} Check if there is already an in-progress request for this host/page combo set i 1 while {[table lookup $table] ne "" } { if {$i == 1} { Mark (to the downstream virtual) this as a queued request by inserting header HTTP::header insert X-mcms-queued "yes" if {[table lookup $table] eq "COND"} { Use the low loop watermark as this object is in cache so stale content could be served set loop_cnt $static::low_loop_cnt } else { Use the high loop watermark as this object is not in cache so stale content cannot served set loop_cnt $static::high_loop_cnt } } Limit the number of times this gets executed so that we know whether it timed out (never returned) or whether the request returned successfully and table entry was deleted by backend virtual if {$i > $loop_cnt} { Exceeded loop count if {$debug} {log local0. "${prefix}Exceeded $loop_cnt, break out of loop"} break } Wait for $static::wait_ms before checking again hopefully by the time the request moves through, WAM will have a valid copy of the page cached after $static::wait_ms incr i } if {$debug && $i > 1 } {log local0. "${prefix}Stopped waiting after $i loops"} if {[HTTP::header exists X-mcms-queued]} { wait just a few milli-seconds to ensure request gets into cache after 10 } Choose downstream virtual (append backend to this virtual name) - WAM processing will take place before traffic hits this next virtual virtual "[virtual]_backend" }
and vs_webapp_backend has the following iRule attached;
when HTTP_REQUEST { set debug 0 if {[HTTP::header exists "X-tls-debug"] } { set prefix [HTTP::header "X-tls-debug"] set debug 1 } Set table name - this MUST match the name used in the iRule on the front-end VIP set table "[getfield [HTTP::host] : 1][string tolower [URI::decode [HTTP::path]]]" Check if conditional GET - this can be used to inform front-end whether to wait a short time (and serve stale content), or a long time if {[HTTP::header exists "if-none-match"] || [HTTP::header exists "if-modified-since"]} { set req_stat "COND" if {[HTTP::header exists X-mcms-queued]} { This was a conditional queued request that was not served from cache - could mean request still in progress but exceeded high_loop_cnt if {$debug} {log local0. "${prefix}Request timed out $table.....invoke stand-in functionality"} HTTP::respond 500 noserver Retry-After 600 return } elseif {[table lookup $table] ne "" || [table lookup "200$table"] ne ""} { Flag indicating request in progress is now set or flag indicating response just returned is set - serve stale if {$debug} {log local0. "${prefix}race condition $table.....invoke stand-in functionality"} HTTP::respond 500 noserver Retry-After 600 return } } else { Mark as non conditional GET set req_stat "N_COND" } } Create table entry with timeout that will allow the high watermark to be reached by queued requests table set $table $req_stat indefinite [expr {int($static::high_loop_cnt * $static::wait_ms / 1000) + 1}] if {$debug} {log local0. "${prefix}session key $table is set to '[table lookup $table]' with expiry [expr {int($static::high_loop_cnt * $static::wait_ms / 1000) + 1}]"} } when LB_FAILED { Either the pool is down, or the selected pool member has failed to complete the 3-way handshake if {$debug} {log local0. "${prefix}LB_FAILED"} Return a 500 to trigger WAM caching 'stand-in' functionality HTTP::respond 500 noserver Retry-After 600 return } when HTTP_RESPONSE { It was a page request for which we have now received a response - delete the flag (table entry) indicating that there is currently an request for this page in progress table delete $table }
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