服务器端功能设计

服务器端以 Web 的形式作为服务平台,以 Django 作为开发框架,结合 rrdtool 模块实现了业务添加(rrdtool create)、报表绘图(rrdtool graph)等功能。另外,项目改用直接操作 SQL 方式来代替 Django 的 ORM,为熟悉 SQL 的人员提供另一种选择。下面详细介绍项目配置及功能实现方法。

Django配置

作为一个新 Django 项目,第一步需要创建一个项目,操作如下:

# cd /data/www
# django-admin.py startproject Servermonitor

在创建的 omaudit 目录中修改 urls.py,添加 App 的 URL 映射规则,内容如下:

from django.conf.urls.defaults import *
urlpatterns = patterns('webmonitor.views',
                       (r'^$', 'index'),  # 映射到index方法,实现前端首页渲染
                       (r'add_do/', 'adddo'),  # 映射到adddo方法,实现新增业务提交服务器端处理
                       (r'add/', 'add'),  # 映射到add方法,实现新增业务页面渲染
                       (r'monitorlist/', 'monitorlist'),  # 映射到monitorlist方法,实现前端扫描记录列表展示
                       )

修改项目 settings.py,关键配置项如下:

import os

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
SYSTEM_NAME = "分布式质量监控平台V1.0"  # 定义系统名称

IDC = {'ct': '电信', 'cnc': '联通', 'cmcc': '移动'}  # 定义采集IDC
RRDPATH = BASE_DIR + "/rrd"  # rrdtool rrd文件存储路径
PNGPATH = BASE_DIR + "/site_media/rrdtool"  # rrdtool生成png存储路径
# 定义webmonitor app路径,调用graphrrd.sh用rrd绘图相关参数
MAINAPPPATH = BASE_DIR + "/webmonitor"
#
TIME_ALARM = 1  # 定义“业务请求响应时间统计”图表告警线阈值(HRULE),单位为秒
TIME_YMAX = 1  # 定义“业务请求响应时间统计”图表Y轴最大值,单位为秒
DOWN_APEED_YMAX = 8388608  # 定义“业务下载速度统计”图表Y轴最大值,单位为字节

项目包括两个 App,其中,webmonitor 为功能应用,publicclass 用于提供公共方法调用。以下结合具体功能对两个 App 进行介绍。

业务增加功能

业务增加模块后台实现了两个功能点:一为将业务信息写入 MySQL 数据库,包括业务名称、监控URL、告警通知方式、探测点及规则等;二为创建所选择的探测点三个图表对应的 rrdtool 文件,图表包括业务请求响应时间统计、业务下载速度、业务可用性统计。前端功能截图如图15-4所示。

image 2023 12 09 18 33 55 523
Figure 1. 图15-4 前端功能截图

创建 rrd 文件功能利用了 rrdtool 模块的 create() 方法实现,实现源码如下:

"""
=创建rrd
-create_rrd(url)
"""
def create_rrd(url):
    URL = url
    domain = GetURLdomain(url)  # 调用GetURLdomain()方法获取URL域名部分
    HID = []
    cur_time = str(int(time.time()))  # 获取当前Linux时间戳,作为rrdool.create方法的 start参数值

    HID = getID(URL)  # 调用getID()方法获取URL对应的所有采集点ID
    for id in HID:  # 遍历采集点ID
        try:
            # 参数指定rrd文件路径,如“项目根目录/rrd/www.baidu.com/17_time.rrd”;
            # step指定步长,设置为300秒,即每隔5分钟收到一个值;start指定第一条记录的起
            # 始时间,使用cur_time变量指定
            rrd_time = rrdtool.create(settings.RRDPATH + '/' + str(domain) + '/' + str(id) + \
                                      '_time.rrd', '--step', '300', '--start', cur_time,
                                      'DS:NAMELOOKUP_TIME:GAUGE:600:0:U',  # 定义数据5个数据源(DS)
                                      'DS:CONNECT_TIME:GAUGE:600:0:U',  # GAUGE计量类型,收到数据后
                                      # 直接存入RRD;
                                      'DS:PRETRANSFER_TIME:GAUGE:600:0:U',  # ‘600’为心跳值,即两
                                      # 个刻度无效时,使用
                                      'DS:STARTTRANSFER_TIME:GAUGE:600:0:U',  # UNKNOWN填充;0:U
                                      # 输入数据的界限
                                      'DS:TOTAL_TIME:GAUGE:600:0:U',
                                      'RRA:AVERAGE:0.5:1:600',  # 定义数据存放格式(RRA),分别为平均、
                                      # 最大、最小合并数据
                                      'RRA:AVERAGE:0.5:6:700',  # 方式,其他参数说明可参考3.2节案例
                                      # 源码说明
                                      'RRA:AVERAGE:0.5:24:775',
                                      'RRA:AVERAGE:0.5:288:797',
                                      'RRA:MAX:0.5:1:600',
                                      'RRA:MAX:0.5:6:700',
                                      'RRA:MAX:0.5:24:775',
                                      'RRA:MAX:0.5:444:797',
                                      'RRA:MIN:0.5:1:600',
                                      'RRA:MIN:0.5:6:700',
                                      'RRA:MIN:0.5:24:775',
                                      'RRA:MIN:0.5:444:797')
            if rrd_time:
                logging.error(rrdtool.error())
            # (其他两张图表rrdtool.create方法类似,此处省略)
        except Exception as e:
            logging.error('create rrd error!' + str(e))

针对 “www.baidu.com” 业务增加成功后,执行 “#ll rrd/www.baidu.com”,输出已生成的 rrd 文件清单,见图15-5。前缀 “17_、18_” 代表不同运营商探测点ID。对采集端而言,一个运营商被视为一个独立业务,产生的数据也是独立的。比如,在增加业务时选择了电信、联通两个运营商探测点,对该业务做数据采集时,将产生两份数据。

image 2023 12 09 18 37 05 711
Figure 2. 图15-5 生成不同运营商的rrd数据文件

业务报表功能

分布式质量监控平台提供了非常丰富的报表功能,常规报表包括最近3小时、当天、当前月、当前年;自定义报表根据选择的时间范围定制。在页面中提交前保持起始时间与结束时间为空则为常规报表,最新3小时报表具体见图15-6。

image 2023 12 09 18 38 19 493
Figure 3. 图15-6 输出业务“当前(最新3小时)”报表

自定义报表根据选择的时间范围进行 rrdtool 查询,结果如图15-7所示。

image 2023 12 09 18 38 50 917
Figure 4. 图15-7 输出自定义时间报表

两种报表实现原理是通过定制 graph 方法的 “--start” 参数来实现,如常规报表中当前、日、月、年图表对应分别为 “-3h、-1day、-1month、-1year”,参数 “--end” 为当前时间;自定义报表采用提交的起始时间与结束时间来对应 “--start” 与 “--end” 参数。平台 rrdtool graph 生成图表时要求有中文支持,但 Python 的 rrdtool 模块没有封装 “--font” 参数,为了解决此问题,最终采用原生 rrdtool 命令行方案,在 Django 中视图中通过 os.system() 方法来调用,实现关键代码如下:

Servermonitor/webmonitor/graphrrd.sh
#!/bin/sh
rrdfile=$1    #接收rrdtool文件路径
pngfile=$2    #接收生成png图片路径
rrdtype=$3    #接收rrd类别,区分定义的三种图表
appname=$4    #接收业务名称
GraphStart=$5    #接收rrdtool起始时间
GraphEnd=$6    #接收rrdtool结束时间
ymax=$7    #接收Y轴最大值
Alarm=$8    #接收告警红线值

#定义两种字体
rrdtool_font_msyhbd="/data/www/Servermonitor/site_media/font/msyhbd.ttf"
rrdtool_font_msyh="/data/www/Servermonitor/site_media/font/msyh.ttf"

if [ "$rrdtype" == "time" ]; then
/usr/local/rrdtool/bin/rrdtool graph ${pngfile} -w 500-h 207 \
-n TITLE:9:${rrdtool_font_msyhbd} \    #定义标题字体
-n UNIT:8:${rrdtool_font_msyh} \    #定义Y轴单位字体
-n LEGEND:8:${rrdtool_font_msyh} \    #定义图例字体
-n AXIS:8:${rrdtool_font_msyh} \    #定义坐标轴字体
-c SHADEA#808080 \    #左上边框颜色
-c SHADEB#808080 \    #右上边框颜色
-c FRAME#006600 \    #数据标记说明边框颜色
-c ARROW#FF0000 \    #X、Y轴箭头颜色
-c AXIS#000000 \    #X、Y轴线颜色
-c FONT#000000 \    #图形所有字体颜色
-c CANVAS#eeffff \    #图形数据区域背景颜色
-c BACK#ffffff \    #图形背景(不含数据区域) 颜色
--title "业务请求响应时间统计-${appname}" -v "速度 (秒)" \    #图表标题
--start ${GraphStart} \    #图表起始时间
--end ${GraphEnd} \    #图表结束时间
--lower-limit=0 \    #限制Y轴的下限
--base=1024 \    #修改1k对应的刻度,默认为1000
-u ${ymax} -r  \    #定义Y轴最大值
DEF:NAMELOOKUP_TIME=${rrdfile}:NAMELOOKUP_TIME:AVERAGE \    #定义数据源及合并统计
                                                              #类型为AVERAGE
DEF:CONNECT_TIME=${rrdfile}:CONNECT_TIME:AVERAGE \
DEF:PRETRANSFER_TIME=${rrdfile}:PRETRANSFER_TIME:AVERAGE \
DEF:STARTTRANSFER_TIME=${rrdfile}:STARTTRANSFER_TIME:AVERAGE \
DEF:TOTAL_TIME=${rrdfile}:TOTAL_TIME:AVERAGE \
COMMENT:" \n" \
AREA:TOTAL_TIME#0011ff:总共时间 \    #用“方块”的形式来绘制“总共时间”数据
#GPRINT定义图表下方的文字说明,参数TOTAL_TIME定义数据来源变量;LAST定义合并(统计)类型,
#指显示当前值;
#其他部分为输出的文字及数值格式
GPRINT:TOTAL_TIME:LAST:"当前\:%0.2lf %Ss"  \
GPRINT:TOTAL_TIME:AVERAGE:"平均\:%0.2lf %Ss"  \
GPRINT:TOTAL_TIME:MAX:"最大\:%0.2lf %Ss"   \
GPRINT:TOTAL_TIME:MIN:"最小\:%0.2lf %Ss"   \
COMMENT:" \n" \
LINE1:NAMELOOKUP_TIME#eeee00:域名解析 \    #用“线条”的形式来绘制“域名解析”数据
GPRINT:NAMELOOKUP_TIME:LAST:"当前\:%0.2lf %Ss"  \
GPRINT:NAMELOOKUP_TIME:AVERAGE:"平均\:%0.2lf %Ss"  \
GPRINT:NAMELOOKUP_TIME:MAX:"最大\:%0.2lf %Ss"  \
GPRINT:NAMELOOKUP_TIME:MIN:"最小\:%0.2lf %Ss"  \
COMMENT:" \n" \
# (“连接时间”、“开始传输”、“第一字节”定义与“域名解析”,此处省略)
HRULE:${Alarm}#ff0000:"(告警值)" \    #输出告警红线值
COMMENT:" \n" \
COMMENT:" \n" \
COMMENT:"\t\t\t\t\t\t\t\t\t\t最后更新 \:$(date '+%Y-%m-%d %H\:%M')\n"
# (其他两张图表rrdtool graph参数类似,此处省略)

生成的图表 png 文件在前端页面中进行引用:

#下面为渲染后的HTML标签
<img  src="/site_media/rrdtool/www.baidu.com/15_time.png?,Math.random();" width="597" />