iRules 101 - #9 – 调试

既然你已经写好了你的第一个iRules :"Hello World",那么现在可以动手来写简单的、比如包含"when HTTP_RESPONSE" 或者 "HTTP::respond 200 content {Hello World}"的irules了,接下来还准备写一些更高级irules。不过,在此之前,首先你需要了解的是如何去调试这些你写的irules代码。本文将介绍几个调试技术,希望可以帮助你构建一个自检测的iRules 。
 
Logging
你可以用来武装你自己的第一个工具是是iRules的 “log”命令。它的语法如下:
log [<facility>.<level>] <message>
facility : "local0", "local1", "local2", "local3", "local4", "local5", "local6", "local7"
level : "alert", "crit", "debug", "emerg", "err", "error", "info", "none", "notice", "panic",  "warn", "warning"
 
facility level这两个参数是可选的,你需要知道的是,当指定了这两个可选参数<facility>.<level>时,将对指令的执行带来显著的、不同的行为。当iRuels在写入log信息时,如果没有facility和/或level参数,则这些Log信息将会被分类并且被限速,也就是说,再限速的期间内,这些Log信息将会被压缩(合并)尽管他们是不同的文本。然而,当指定了facility和/或者level参数的时候,这些Log信息将不会被限速(尽管syslog-ng仍然会对重复的内容进行压缩)。
 
 
这两个参数的可选项有很多,幸运的是,只有在需要自定义一些特殊的Syslog-ng时才需要明确指定这两个参数,通常你只需要使用默认值就可以了,<facility>. 和<level>的默认值分别是”local0”和”error”。而事实上,我们已经简化了你的操作,你完全可以省略level 这个参数,因为我们会自动将它添加上。DevCentral中的每一个iRule ,几乎99%是使用下面的语法来记录log的,这种用法几乎可以满足所有需求。
 
log local0. "message goes here"
 
这样写的好处是确保记录日志信息时将不受到写入限制,可以直接写入日志文件,它们将被储存在系统的log文件: /var/log/ltm。
 
一个实际的例子
 
那些需要log,那些不需要log取决于你的iRule和你需要努力达到的目地。如果你想处理HTTP的请求,那么使用irules 的log记录一些输入信息是很好的做法,比如记录HTTP::host和HTTP::uri,记录一些临时的变量也是很好的想法,如果你需要处理这些字符串的话。让我们来看看下面的iRule: 
when HTTP_REQUEST {
  switch -glob [HTTP::uri] {
    "/app1*" {
      pool app1_pool
    }
    "*.gif" -
    "*.jpg" {
      pool images_pool
    }
    default {
      pool def_pool
    }
  }
}

显而易见。上述irules中所有发送到应用程序“/app1”的请求将被发送到app1_pool中,所有访问扩展名为 “.gif”和“ .jpg”文件的请求将被发送到images_pool中,其余的所有请求将被发送到def_pool中。然而当我们测试这个irules时,会发现app1应用中的图片显示不出来。为什么呢?那么调试这个问题的方法是将iRules的逻辑判断元素记入日志记录中,以确定问题的根源。

 

首先想到的是查看Web服务器中有关image服务器的日志,检查为什么请求没有得到响应。让你惊讶的是,log中的记录显示并没有请求到达image服务器。那么接下来很明显我们需要调试一下iRule ,来仔细看看究竟什么原因导致了这个问题。下面是改后的irules: 

when HTTP_REQUEST {
  log local0. "Request: [HTTP::uri]"
  switch -glob [HTTP::uri] {
    "/app1*" {
      log local0. "Sending request to app1_pool"
      pool app1_pool
    }
    "*.gif" -
    "*.jpg" {
      log local0. "Sending request to images_pool"
      pool images_pool
    }
    default {
     log local0. "Sending request to def_pool"
      pool def_pool
    }
  }
}

测试后,你会在log中看到像这样的记录: 

...
Request: /app1/index.html
Sending request to app1_pool
Request: /js/file.js
Sending request to def_pool
Request: /app1/smile.gif
Sending request to app1_pool

根据上面的irules,你可能认为所有的图像文件的请求都应该被发送到images_pool中,但事实上他们却被发送到了app1_pool中。这是由于在irules中请求先匹配了“app1”,所以会请求发送往app1_pool中的服务器中,而不会继续向后查找匹配项。现在,知道了这些信息以后,那么可以重新调整switch语句中的条件处理顺序,以确保所有对图片的请求发往images_pool中。调整后如下: 

when HTTP_REQUEST {
  log local0. "Request: [HTTP::uri]"
  switch -glob [HTTP::uri] {
    "*.gif" -
    "*.jpg" {
      log local0. "Sending request to images_pool"
      pool images_pool
    }
    "/app1*" {
      log local0. "Sending request to app1_pool"
      pool app1_pool
    }
    default {
      log local0. "Sending request to def_pool"
      pool def_pool
    }
  }
}

 

现在好了,所有的图像都能正常显示了。正如你在日志中看到的内容: 

...
Request: /app1/index.html
Sending request to app1_pool
Request: /js/file.js
Sending request to def_pool
Request: /app1/smile.gif
Sending request to images_poo

 

问题似乎解决了,所有的应用都能正常访问,并且图片也都能正常显示。大功告成了吗?错...
 
删除调试用的log
 
logging是调试过程中一个很有用的工具,甚至可以确定服务器上发生的一些问题。但是,系统磁盘只有这么大,而使用log命令记录日志信息会占用一定的空间,在大多数情况下,应该将调试用的logging disable。可以采取多种方式来实现。
 
1、第一种方法:在iRule中将调试用的log命令删除。这是最简单的方法,只要删除log命令那一行,然后保存便可以了。这样做可以简化你的iRule 并且更易于阅读。
 
2、               第二种方法:使用注释符:“#”符号注释掉log命令。这样做的好处是:当你需要调试一个新的应用错误时,你可以轻松地恢复这些日志命令,只需要删除掉“#”符号取消对日志的注释,单击保存,便可以回到以前的状态了。
 

3、               第三种方法:使用全局变量来控制日志命令。具体是现实通过if语句判断变量的值,这样就可以像使用变量一样来启用或禁用log命令。上述iRule可以这样写:

 

when HTTP_REQUEST {
  set DEBUG 1
  if { $DEBUG } { log local0. "Request: [HTTP::uri]" }
  switch -glob [HTTP::uri] {
    "*.gif" -
    "*.jpg" {
      if { $DEBUG } { log local0. "Sending request to images_pool" }
      pool images_pool
    }
    "/app1*" {
      if { $DEBUG } { log local0. "Sending request to app1_pool" }
      pool app1_pool
    }
    default {
      if { $DEBUG } { log local0. "Sending request to def_pool" }
      pool def_pool
    }
  }
}

 

这样,可以通过设置DEBUG 变量的值为1来启用logging或者为0来关闭loging。使用那种方法完全取决于你的实际环境。第一种方法和第二种方法不会占用CPU来处理log程序,但第三种方法会进行一次布尔类型变量的检测。如果面对成百上千的请求 ,这也是不容忽视的
 
总结
 
最后,首先要牢记在心的logging工具是个很好的助手。你应该养成使用它来调试你的irules的习惯,这样可以加快iRules开发的问题分析速度。但不要忘记在将iRules放到生产环境的时候将那些调试命令注释掉,这样避免你把BIG-IP的文件系统充满。
Published Feb 02, 2009
Version 1.0

Was this article helpful?

No CommentsBe the first to comment