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命令工作机制,这时最好是借助于厂家技术支持中心进行优化。