事件是iRules构建的基石。事件是iRule对TCL语言的一个扩展,它使我们一个基于连接的状态上下文内来进行模块化的编程。本文将围绕事件的细节展开讨论并且了解他们是如何在相同的虚拟服务器中被一个或多个iRule调用的。
 
Rule 1: 一个虚拟服务器可以包含一个或多个iRule.
 
首先,一个很重要的事实是iRules仅仅是一段脚本代码。他不能在一个虚拟服务器的上下文之外做很多的事情。iRule作为“资源”存在在虚拟服务器中,并且在一个虚拟服务器的资源列表中可以有0-N个iRule,在一个虚拟服务器中调用多种iRule会有很多好处,这些将会在以后的章节里讲到。
 
Rule 2: 一个iRule可以由一个或多个不同的事件代码构成.
 
很明显的,从iRules代码共享区的示例代码来看,你无需为多个不同的事件而编写不同iRules。一个iRule中可以包含一个或者多个事件,以下是一个iRule包含多个事件的实例:
 
when HTTP_REQUEST {
  set uri [HTTP::uri]
  log local0. "Received Request for uri '$uri' from client.  Sending to server..."
}
when HTTP_RESPONSE {   log local0. "Received Response for uri '$uri' from server.  Sending to client..." }
 
Rule 3: 一个iRule可以由一个或多个类似的事件构成.
 
在同一个iRule里可以包含许多“类似”事件并不多见。你必须为每一个"类似"事件指定优先级以决定iRule的处理次序来告诉iRules的处理引擎按照你希望的顺序来执行每一个事件代码. 每一个事件都有一个默认为500的优先级,优先级的有效值区间为0-1000。在iRule的“Prority”命令说明会有很多关于优先级用法的详细资料. 以下的实例说明相类似的事件可以被使用在同一个iRule里。
 
when HTTP_REQUEST priority 200 {
 log local0. "I'm a priority 200, I'll get executed second."
when HTTP_REQUEST priority 100 {
 log local0. "I'm a priority 100, I'll get executed first."
}
 
这时你可以问自己:”为什么我需要在一个Rules中使用这些“类似”的事件呢?我认为我可以在单一的事件代码中就可以完成工作了。”。
 
在那些琐碎的iRules中,这样做的意义并不是很明显。但是,当你开始搭建一系列的iRules并且开始深入到如何使用他们的时候,你将可能开始审视代码中的格式。比如你所有的HTTP_REQUEST时间的开始看上去都是这样的:
 
when HTTP_REQUEST {
 log local0. "URI Requested [HTTP::uri]"
 # Do something unique.
}
 
当你想要改变你的所有的100个iRules中的第一行时,问题出现了。或许你已经厌倦了看见日志文件里面全是URI请求,也或许你想在输入的日志中添加其他的信息。 这时你有两个选择:第一,你可以逐个修改每个iRule代码相似的地方,然后在下一次你想进行修改的时候再做一次同样的事情。其次, 你也可以使用模块化编程来解决这个问题,首先我们可以把代码的“公共”部分,让它被编写在一个优先级非常低iRule中。然后,你可以为每一个虚拟服务器添加一个“公共”的iRule以及各自不同的iRules代码。这时上面的irule看上去将是这样的:
 
when HTTP_REQUEST priority 100 {
 log local0. "URI Requested [HTTP::uri]"
when HTTP_REQUEST priority 200 {
 # Do something unique
}
 
现在,改变Log的数据值需要改变一个iRule,而不是你以前所管理的100个iRule.这是一个非常简单的例子,但是也必须要举一反三。如果你在虚拟服务器里配置了了认证,SSL卸载,执行HTTPS重定向或者其他使用iRules完成的更有趣的工作,你就会发现使用模块化编程的好处了。
 
Rule 4: 不能从一个iRule中调用另外一个iRule
 
如何从一个iRules调用另外一个iRules的问题经常被问起,还有就是如何在iRules调用之间进行变量的传递。我们已经关闭了这种可以直接从一个iRule中调用另外一个iRule的"程序调用"功能. 但是,通过使用多个iRules和将“类似“的iRules按照优先级执行,已经可以非常直接的设置事件被执行的顺序。Session变量可以被用于在不同的事件代码段之间传递信息。默认情况下,所有变量都是基于“连接”的(除了在RULE_INIT中定义的变量),意味着他们只存在于连接的生命周期期间(请求/应答)。在连接结束之后,这个会话变量会被系统回收。
 
在第一个例子中,可以看见一个包含"[HTTP::uri]"的变量在第一个事件中被创建,并在第二个事件中被调用,不管事件本身是相同还是不同这些都是可以做到的。Session变量的使用可以模拟在程序调用之间的参数传递行为。
 
结论:
 
在同样的iRule里可以更灵活的包含多种不同或相同的事件,同时在一个虚拟服务器中应用多个iRule,可以更加方便的实现模块化的编程,并且让iRule的设计者们可以更有效率的设计和维护iRule。