A10網絡的的aFleX腳本可以對請求和響應數據包進行深度檢測并進行靈活的重定向、丟棄、修改等操作,可以解決用戶的一些特殊需求,因此深受一批技術型用戶的鐘愛。盡管AX平臺憑借其杰出的架構設計使得aFleX帶來的性能影響相對同類產品小很多,但根據aFleX的復雜度和編寫質量不同,對應用整體性能的影響還是存在一些差別的。本文就如何編寫更高效的aFleX進行簡單闡述。
首先,哪些因素會影響aFleX性能? 有以下幾點。
-
做什么操作(使用什么aFleX/tcl命令)? 如對數據包內容進行操作要比對數據包頭操作要耗費的資源要大很多。
-
變量、條件判斷、循環等的使用
-
使用什么事件? 如RAM CACHE中,在CACHE_RESPONSE事件中處理(每次命中該緩存都需要處理)和在緩存前的HTTP_RESPONSE事件中處理(只在緩存前處理一次),資源使用差別巨大。
知道了影響aFleX性能的因素,如何編寫高效的aFlex就又針對性了。基本原則如下。
1. 別使用aFlex!
不要因為好玩使用aFleX,除非必須。如果有相應的功能特性可以做到同樣功能,使用設備自身的功能。AX的HTTP模板中提供插入客戶端IP、URL 交換、HTTP頭刪除/插入/修改、HTTP重定向等豐富的功能,性能要比使用aFleX更好。
2. 避免沒必要的變量
除非必須,否則盡可能不要使用變量。變量創建、賦值等都需要耗費CPU資源,同時也會占用內存資源(每個連接都會占用一定字節,在大并發用戶時影響會放大)。諸如HTTP::host 和 IP::client_addr等命令的執行結果已經緩存在內存中,將這些常量結果保存到變量是典型的資源浪費。只有在使用變量可以減少重復計算該值時才使用變量。下面例子中,前者就使用了沒有必要的變量。
未優化:
set ip_addr [IP::client_addr]
log “Client address=$ip_addr”
優化后:
log “Client address=[IP::client_addr]”
3. 使用{}括住expr表達式!
由于tcl語言的表達式有兩次替代,一次tcl解釋器替代和一次expr命令替代,盡可能使用{}括住表達式。這樣可以使tcl對于沒必要的二次替換的變量和命令結果只進行一次替代。
如set octet [expr 3 + [getfield [IP::client_addr] "." 4]] 中[getfield [IP::client_addr] "." 4]在tcl解釋器中替代一次,在進行expr計算時還有一次替代。
而在使用{}后,set octet [expr {3 + [getfield [IP::client_addr] "." 4]}] 不需用第2次expr命令中的替代。
4. 條件判斷時遵循以下原則
-
盡可能使用if-elseif替代連續多個if。多個if時,即使匹配后仍然需要執行完所有if。if-elsif則會在首次匹配后退出條件判斷。
-
if-elseif中盡量把最可能的條件放到最前面。
-
盡可能使用switch替換if-elseif。switch可以讓代碼看起來簡單,也更優化。
5. 數據查詢時盡量使用tcl中的array替代list。多維矩陣的查詢膠質多個list查詢更高效。
6. 使用正確的操作符可以改善性能。如:
-
字符串比較使用eq和ne
-
數字比較使用 ==和 !=
-
使用命令 [IP::addr] 比較地址
7. 盡可能避免使用正則表達式regex和正則表達式替代regsub。這兩個命令功能強大,但耗費資源也更多。有些情況必須使用正則表達式就不得不犧牲一些性能。可能的情況下盡可能使用以下替代命令。
-
starts_with, ends_with等替代regexp
-
string map替代regsub
以上只是部分常見的可以優化aFleX的地方,可以滿足大部分情況。針對非常復雜的aFleX優化,一方面需要非常熟悉tcl,另一方面需要熟悉aFleX命令工作機制,這時最好是借助于廠家技術支持中心進行優化。