varnish配置内嵌C语言时间处理

 

公司网站有很多用到取服务器时间的jsonp请求,比如限时尊抢每天准时11点上线,就需要用ajax请求取服务器时间。此功能简单且访问量较大,因此决定将该ajax请求后端服务器的功能迁到varnish里。感谢varnish的vcl语言对应内嵌C功能,使得我们可以在varnish截获请求并反馈回当前时间即可。整个功能比较简单,设计思路是这样的,在vcl中的vcl_recv里截获到对服务器请求时间URL的访问,直接error回一个自定义的statuscode,此处最好用扩展的statuscode(用http协议里的状态值也可以实现,但是需要在response里做标记以便在vcl_error返回之前做判断),代码片段如下:

   sub vcl_recv {

      ##略去其他配置
      if (req.url ~ "(?i)/xxxx/GetTime.aspx" ) {
        error 606 "mark";
      }
      ##略去其他配置
    }

然后在vcl_error里捕捉这个error并计算时间,然后输出。代码如下:

 sub vcl_error {

  ###注意此处判断我们自定义的Status Code 
  if (obj.status == 606){

  ###注意将最终Deliver的状态转化为200
  set obj.status = 200;
  set obj.response = "OK";
  C{
    static void *reg;
    VRT_re_init(&reg, "(?i)/xxxx/gettime.aspx\\?callback=");
    char *callback = (char*)VRT_regsub(sp, 0,VRT_r_req_url(sp),reg, "");

    char buf[30];
    time_t clock = time(NULL)+28800;
    struct tm *tm = gmtime(&clock);
    strftime(buf,sizeof(buf),"%Y/%m/%e %T",tm);
    char json[strlen(callback)+33];
    char *prefix = strcat(callback, "({\"timer\":\"");
    strcpy(json,prefix);
    strcat(json,buf);
    strcat(json,"\"})");
    VRT_re_fini(reg);
    VRT_synth_page( sp, 0, json, "", "", "", vrt_magic_string_end) ;
  }C
  return(deliver);
}

 

Okay,这样就搞定。

下面再说一下这个版本之前的一个问题。

由于用到了C的时间处理函数(本人没有写过C程序,用起来还是挺费劲的:),各路C高手勿拍板砖哈:)),在最初版本中遇到了一个令人汗颜的问题。

为了能支持不同的时区设置的服务器,因此用到了取gmt时间的函数,同时将此时间+8个小时转换为北京时间,在做这个转换时用到的代码如下:

  time_t clock = time(NULL);
  struct tm *tm = gmtime(&clock);
  tm->tm_hour += 8;

此转换在北京时间0~8点之间工作会出现严重的异常。(想想自己是个C语言盲,习惯了C#代码,轻信了tm结构的文档),没有多想在GMT时间16:00~24:00时会得到tm->tm_hour大于24的情况,导致取得的时间格式错误。

想想真后怕,也算是给自己提个醒吧。

posted on 2012-08-31 17:47  安华若川  阅读(408)  评论(0编辑  收藏  举报