terminal services
1 TopicReal Least Connections iRule
Problem this snippet solves: Due to BIG-IP TMOS CMP (Clustered MultiProcessing) architecture, customers that desire least connections behavior for LB will occasionally see uneven LB behavior because each TMM is operating independently and they could (for example) each send 1 connection to pool member A for a total of 2 connections while pool member B has 0 connections. This iRule addresses this issue by using table memory to track the server with the highest number of concurrent connections (table entry "highconn") and if a new LB decision would cause that count to be exceeded, checks to see if all servers have that number of connections; if not, it will force an LB::reselect. This iRule not recommended for high connection rate virtual servers, but is useful for any application that is particularly sensitive to uneven load balancing (e.g. a terminal services or VDI scenario). How to use this snippet: Apply iRule to Virtual Server and use whichever load-balancing algorithm you desire (BIG-IP will use that to make initial LB decision); iRule will do everything it can to "force" least connections behavior. Code : # Real Least Connections - For applications sensitive to imperfect least connections load balancing that occurs due to BIG-IP TMOS CMP Architecture # c.jenison at f5.com (Chad Jenison) when RULE_INIT { set static::vs ssh7 set static::debug 1 } when CLIENT_ACCEPTED { } when LB_SELECTED { if {[table lookup $static::vs+highconn] >= 0} { if {[table lookup $static::vs+[LB::server addr][LB::server port]] >= [table lookup $static::vs+highconn]}{ if { $static::debug != 0 } { log "server [LB::server addr]:[LB::server port] with conns: [table lookup $static::vs+[LB::server addr][LB::server port]] at or higher than highconn: [table lookup $static::vs+highconn]" } if {[table keys -subtable $static::vs+[table lookup $static::vs+[LB::server addr][LB::server port]] -count] < [active_members [LB::server pool]] && [table lookup $static::vs+[LB::server addr][LB::server port]] != 0} { LB::reselect if { $static::debug != 0 } { log "Reselecting (default LB picked: [LB::server addr]:[LB::server port]) due to uneven load" } } else { table incr $static::vs+highconn if { $static::debug != 0 } { log "Increased highconn to: [table lookup $static::vs+highconn]" } } } else { if { $static::debug != 0 } { log "Selected Server [LB::server addr]:[LB::server port] has: [table lookup $static::vs+[LB::server addr][LB::server port]] connections, adding another." log "highconn: [table lookup $static::vs+highconn]" } } } else { table set $static::vs+highconn 1 if { $static::debug != 0 } { log "Pool [LB::server pool] in use with max of 1 connection" } } } when SERVER_CONNECTED { if {[table lookup $static::vs+[LB::server addr][LB::server port]] >= 0} { table incr $static::vs+[LB::server addr][LB::server port] } else { table set $static::vs+[LB::server addr][LB::server port] 1 } table set -subtable $static::vs+[table lookup $static::vs+[LB::server addr][LB::server port]] [LB::server addr][LB::server port] "" if { $static::debug != 0 } { log "Connected to Pool Member: [LB::server addr]:[LB::server port] - ConnCount: [table lookup $static::vs+[LB::server addr][LB::server port]]" } } when SERVER_CLOSED { if { $static::debug != 0 } { log "[IP::server_addr]:[TCP::server_port] closed connection" } if {[table keys -subtable $static::vs+[table lookup $static::vs+[IP::server_addr][TCP::server_port]] -count] == 1 && [table lookup $static::vs+[IP::server_addr][TCP::server_port]] == [table lookup $static::vs+highconn]} { table incr $static::vs+highconn -1 if { $static::debug != 0 } { log "Decremented highconn to: [table lookup $static::vs+highconn]" } } table delete -subtable $static::vs+[table lookup $static::vs+[IP::server_addr][TCP::server_port]] [IP::server_addr][TCP::server_port] table incr $static::vs+[IP::server_addr][TCP::server_port] -1 if { $static::debug != 0 } { log "Server Connection Closed for [IP::server_addr]:[TCP::server_port] - Count: [table lookup $static::vs+[IP::server_addr][TCP::server_port]]" } } Tested this on version: 12.0264Views0likes3Comments