awstats CGI模式下动态生成页面缓慢的改进

本文可以看做是 http://kaifly.blog.51cto.com/3209616/1719248 这篇文章的下篇,在使用过程中发现awstats在cgi模式下动态生成分析报告慢的问题 (尤其是有些站点每天两个多G的日志,查看起来简直是在考验人的耐性),本文分享一种改造这个缺点的思路。


首先再来总结下awstats的处理过程以及查看分析结果的两种方式,来看官方版说明:

Process logs: Building/updating statistics database,建立/更新统计数据库(包含统计结果的文本文件)命令如下
  perl awstats.pl -config=mysite -update
Run reports: Building and reading reports(生成并阅读报告)
1.The first option is to build the main reports, in a static HTML page, from the command line, using the following syntax
  第一种方式,通过命令行生成html文件,然后浏览器展示。命令如下
  perl awstats.pl -config=mysite -output -staticlinks > awstats.mysite.html
2.The second option is to dynamically view your statistics from a browser.  To do this, use the URL:
  第二种方式,通过如下的url“动态”的生成该站点的分析报告
  http://www.myserver.mydomain/awstats/awstats.pl?config=mysite

总体思路就是,既然“动态生成”这个过程耗时,那就在服务器上定时通过curl 请求每个站点对应的url将生成的html页面存储到特定位置,然后浏览器访问时直接读取html文件即可(可能有同学要问了,这么费事,那为啥不直接用上面的第一种方式,用awstats.pl提供的参数直接生成html文件呢?这也就回归到上篇文章中讨论过的两种方式的差别了,awstats.pl生成的静态html页面从易用性和美观性都不如通过CGI动态生成的html页面)

思路有了,接下来就是“尝试”和“分析特征”。我们直接以

curl  -o /tmp/mysite.html http://www.myserver.mydomain/awstats/awstats.pl?config=mysite

得到的页面源代码如下

<html >
<head>
<meta name="generator" content="AWStats 7.4 (build 20150714) from config file awstats./usr/local/awstats/etc/www.conf.conf (http://www.awstats.org)">
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="expires" content="Wed Apr 27 11:09:58 2016">
<meta http-equiv="description" content="Awstats - Advanced Web Statistics for www.dmzj.com (2015-08) - main">
<title>Statistics for www.mysite.com (2015-08) - main</title>
</head>

<frameset cols="240,*">
<frame name="mainleft" src="awstats.pl?config=mysite&amp;framename=mainleft" noresize="noresize" frameborder="0" />
<frame name="mainright" src="awstats.pl?config=mysite&amp;framename=mainright" noresize="noresize" scrolling="yes" frameborder="0" />
<noframes><body>Your browser does not support frames.<br />
You must set AWStats UseFramesWhenCGI parameter to 0
to see your reports.<br />
</body></noframes>
</frameset>

</html>

可以看到动态生成的页面实际上是一个包含了两个frame(mainleft和mainright)的html文件,也就是说,如果我们想还原一个动态生成的报告页面,需要通过如下三条命令来生成对应的三个文件

curl -s -o main.html "http://www.myserver.mydomain/awstats/awstats.pl?config=mysite"    #取得主页面
curl -s -o left.html "http://www.myserver.mydomain/awstats/awstats.pl?config=mysite&framename=mainleft"    #取得左frame
curl -s -o right.html "http://www.myserver.mydomain/awstats/awstats.pl?config=mysite&framename=mainright"    #取得右frame

然后,需要在 main.html中修改mainleft和mainright两个frame的src属性,将其指定到我们生成的left.html和right.html。如此我们就实现了将动态页面静态化(实际上是把动态生这个等待时间放到脚本里定时执行了)。

接下来,就是具体的实现过程了,涉及到对上篇文章中“cron_awstats_update.sh”脚本的改进,修改后的脚本内容如下(注释还算丰富,也能帮助理解思路)

#!/bin/sh

#awstats日志分析
basedir=/usr/local/awstats
date_y_m=$(date +%Y%m -d ‘1 day ago‘)    #因为该脚本是第二天凌晨分析前一天的日志

cd $basedir
#循环更新所有站点日志统计信息
echo -e "\e[1;31m-------`date "+%F %T"`    开始处理---------\n\e[0m" >>logs/cron.log
for i in `ls result/`
do
    echo -e "\e[1;32m -----`date "+%F %T"`  处理 $i 日志-----\e[0m" >>logs/cron.log
    perl wwwroot/cgi-bin/awstats.pl -config=etc/$i.conf -lang=cn -update &>>logs/cron.log

    #将动态页面静态化,查看展示页面结构可得:主页面基本没内容,主要靠左右两个frame来生成内容
    #所以可以将每一个站点的展示页分为三部分来缓存
    echo -e "\e[1;32m -----`date "+%F %T"`  生成 $i 分析静态页面-----\n\e[0m" >>logs/cron.log
    cd wwwroot    #进入wwwroot目录,并以 ‘站点/日期‘为格式创建目录用来存储html文件
    if [ ! -d $i/$date_y_m ];then mkdir -p $i/$date_y_m;fi
    cd $i/$date_y_m
    curl -s -o main.html "http://www.myserver.mydomain/cgi-bin/awstats.pl?config=$basedir/etc/$i.conf"    #取得主页面
    curl -s -o left.html "http://www.myserver.mydomain/cgi-bin/awstats.pl?config=$basedir/etc/$i.conf&framename=mainleft"    #取得左frame
    curl -s -o right.html "http://www.myserver.mydomain/cgi-bin/awstats.pl?config=$basedir/etc/$i.conf&framename=mainright"    #取得右frame

    #修改main.html里关于左右两个frame的引用
    sed -i -e ‘s/awstats.pl.*left/left.html/g‘ -e ‘s/awstats.pl.*right/right.html/g‘ main.html
    #接下来修改上面三个文件中的超链接部分以及字符集
    sed -i -e ‘s#awstats.pl#http://www.myserver.mydomain/cgi-bin/awstats.pl#g‘           -e ‘s/charset=.*/charset=utf-8">/g‘           -e ‘s/lang="cn"//g‘           main.html left.html right.html
    
    cd $basedir
done
echo -e "\e[1;33m-------`date "+%F %T"`  处理完成---------\n\e[0m" >>logs/cron.log

经过脚本处理之后,在wwwroot目录下,站点目录与html文件会是这个样子

到此,我们对上篇文章中的nginx配置部分做相应修改后就可以通过如下url来访问了

http://www.myserver.mydomain/www/201605    #表示www站2016年5月的统计页面

但是,改造到这里并不算完,在动态生成的页面里,有选择年和月的下拉框,可以查看指定年月的统计页面,如下图

这个功能会产生一个如下的请求
http://www.myserver.mydomain/cgi-bin/awstats.pl?month=04&year=2016&output=main&config=www.conf&framename=index

仍然是动态请求(即仍然会慢),但按照我们的设计,每个月应该都已经生成了静态文件,所以是不需要动态生成的。如何将这个功能点修改为也按照上面静态url的格式呢,这里作者首先想到了两个方案:
  一个是通过js获取年和月的值,然后在表单的action处拼出所需的url
  另一个是通过nginx的rewrite来实现
经过尝试和对比,第二种方案更适合这里的场景,因为第一种涉及到对生成的html文件内容进行修改,且不止一处,实现起来啰嗦一些;而第二种方案只需要在nginx里做配置即可(这里如何从nginx获取到参数值并且引用该值算是一个小技巧吧)。

最终,修改之后的nginx配置文件如下

server {
    listen   800;
    root /usr/local/awstats/wwwroot;
    access_log /tmp/awstats_access_log access;
    error_log /tmp/awstats_nginx.error_log notice;

    location / {
        index index.html main.html;
    }

    # Static awstats files: HTML files stored in DOCUMENT_ROOT/awstats/
    location /awstats/classes/ {
        alias classes/;
    }
    location /awstats/css/ {
        alias css/;
    }
    location /awstats/icon/ {
        alias icon/;
    }
    location /awstats-icon/ {
        alias icon/;
    }
    location /awstats/js/ {
        alias js/;
    }

    # Dynamic stats.
    location ~ ^/cgi-bin/(awredir|awstats)\.pl.* {
        gzip off;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME $document_root/cgi-bin/fcgi.php;
        fastcgi_param X_SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param X_SCRIPT_NAME $fastcgi_script_name;
        include fastcgi_params;

        fastcgi_send_timeout 300;

        #为了让顶部根据时间筛选功能也能用上之前生成的静态页面, 其中%2F部分为url编码后的/,为了取得站点名
        if ($query_string ~* "^month=(\d+)&year=(\d+)&output=main&config=.+etc%2F(.+)\.conf&framename=index$") {
            set $month $1;
            set $year $2;
            set $site $3;
            rewrite  ^/cgi-bin/awstats\.pl  /$site/$year$month? permanent;
        }
    }
    expires 12h;
}

ok,到这里整个改进过程完毕。每个月份的统计结果的主页面都已经实现了静态化,查看时再也不用经历漫长的等待了!
  PS: 工具再好,也不见得完全适合或者满足自己的需求,大部分情况下作为“软件使用者”的运维同胞,应该有这个意识:不只会用,必要时还能改。共勉!

时间: 2024-10-10 10:29:27

awstats CGI模式下动态生成页面缓慢的改进的相关文章

【案例分享】使用ActiveReports报表工具,在.NET MVC模式下动态创建报表

提起报表,大家会觉得即熟悉又陌生,好像常常在工作中使用,又似乎无法准确描述报表.今天我们来一起了解一下什么是报表,报表的结构.构成元素,以及为什么需要报表. 什么是报表 简单的说:报表就是通过表格.图表等形式来动态显示数据,并为使用者提供浏览.打印.导出和分析的功能,可以用公式表示为: 报表 = 多样的布局 + 动态的数据 + 丰富的输出 报表通常包含以下组成部分: 报表首页:在报表的开始处,用来显示报表的标题.图形或说明性文字,每份报表只有一个报表首页. 页眉:用来显示报表中的字段名或对记录的

动态生成页面(二)

在上篇文章<动态生成页面(一)--ASP.NET中Literal使用>中,介绍了通过Literal容器动态加载页面.但在取值过程中遇到了一些问题.但是因为拼接的控件textbox为服务器控件,所以在取值过程中遇到一些问题. 几经周转,最后无奈改变了实现方法.直接实例化出控件,然后添加到页面中.具体实现过程如下: 前台页面: <body> <form id="form1" runat="server"> <div id=&qu

OSG立体模式下动态修改相机远近裁剪面的实现

1. 非立体模式下动态修改相机远近裁剪面 class GLB_DLLCLASS_EXPORT CGlbGlobeClipHandler : public osg::NodeCallback    { struct CustomProjClamper : public osg::CullSettings::ClampProjectionMatrixCallback  { template<class matrix_type, class value_type>            bool _

05---MVC模式下动态调整Cell高度三部曲

动态调整Cell高度三部曲 我们在做项目开发的过程中经常会遇到每一个cell的高度及cell的子控件的显示个数不同,以我最近开发的微格为例,讲解一下MVC模式动态的调整Cell宽高的三部曲 1>.自定义Cell,重写- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier方法 在此方法中添加所有的可能显示的子控件 子控件的frame通过构建的cellFrame模型进行设置

动态生成页面(一)——ASP.NET中Literal使用

在页面中加入内容时,假设是静态内容.无需使用容器,能够直接将标记作为HTML直接加入到页面中:可是,假设是动态内容,则必须借助容器将内容加入到页面中.典型的容器有:Label控件.Literal控件.Panel控件和PlaceHolder控件. 一.控件选择:Literal Literal控件与Lable控件的差别在于,Literal控件不向文本中加入不论什么HTML元素:而Label控件呈现一个span元素. Panel和PlaceHolder控件呈现为DIV元素.这将在页面上创建离散块,与L

ASP.NET中Literal使用——动态生成页面

在页面中添加内容时,如果是静态内容,无需使用容器,可以直接将标记作为HTML直接添加到页面中:但是,如果是动态内容,则必须借助容器将内容添加到页面中.典型的容器有:Label控件.Literal控件.Panel控件和PlaceHolder控件. 一.控件选择:Literal Literal控件与Lable控件的区别在于,Literal控件不向文本中添加任何HTML元素:而Label控件呈现一个span元素. Panel和PlaceHolder控件呈现为DIV元素,这将在页面上创建离散块,与Lab

log4net在release模式下无法生成文件或不写入日志

在Debug模式一切正常,但是在release模式下log4net不工作,查了很多资料,终于解决.具体做如下检查修改. 1.检查log4net写入日志文件路径是否正确: 2.检查对应日志文件路径是否有权限: 3.检查程序log4net配置获取路径: 最常见的问题是第三步,一般都是在AssemblyInfo.cs文件中写入如下代码 [assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Config

sitemap.xml 静态和动态生成页面 shopnc二次开发 动态生成sitemap.xml

Sitemap 可方便网站管理员通知搜索引擎他们网站上有哪些可供抓取的网页.最简单的 Sitemap 形式,就是XML 文件,在其中列出网站中的网址以及关于每个网址的其他元数据(上次更新的时间.更改的频率以及相对于网站上其他网址的重要程度为何等),以便搜索引擎可以更加智能地抓取网站. 目前有两种格式 一.Google SiteMap <urlset xmlns=“网页列表地址”> <url> <loc>网址</loc> <lastmod>2005

动态生成页面(从数据库中动态取出数据信息生成页面)

做课程设计的时候  做的有点烦了  所以就简单的写了点 以下就是将添加到购物车的商品动态的显示到前台页面的代码 首先是我的head.jsp这里面的"我的目录"使用的不是直接链接而是一个servlet名称叫做"selectUserCart" 我的里面使用的user.books.userAccout类都是基本的记录了基本信息的类为其实现setXxx()和getXxx()方法 <%@ page language="java" import=&qu