系统环境部署

系统环境说明

前面介绍了分布式质量监控平台的三种角色,为了便于读者理解,下面对不同角色的环境、实现方法进行详细说明,环境设备角色表如表15-1所示。

image 2023 12 09 18 16 45 260
Figure 1. 表15-1 系统环境说明表

数据采集角色

数据采集功能角色需要完成两个任务:一为采集远程业务服务集群 HTTP 响应数据,并将数据写入远程 MySQL 数据库;二为提供异常 HTTP 响应告警支持。本示例部署 192.168.1.20、192.168.1.21 主机,分别模拟电信与联通网络。下面详细说明。

数据采集端只有两个 Python 文件,一个为 config.py,其定义了数据库信息、运营商网络代码、连接超时时间等,内容如下:

detector/config.py
# -*- coding: utf-8-*-
# 定义MySQL数据信息
DBNAME = 'WebMonitor'
DBUSER = 'webmonitor_user'
DBPASSWORD = 'SKJDH3745tgDTS'
DBHOST = '192.168.1.10'
# 修改成探测运营商网络代码(重要)
# settings.py中定义IDC={'ct':'电信','cnc':'联通','cmcc':'移动'}
# “ct”代表电信探测点网络,联通网络修改成“cnc”,移动网络修改成“cmcc”,其他类似
IDC = "ct"
# 连接的等待时间
CONNECTTIMEOUT = 5
# 请求超时时间
TIMEOUT = 10
# 告警邮件地址
MAILTO = "user1@domain.com,user2@domain.com"
# 告警手机号
MOBILETO = "136****3463"

另一个为提供业务服务质量采集功能的 runmonitor.py,采用了 pycurl 模块实现,通过定义 setopt() 方法定量参数,模拟一个 HTTP 请求器(request),也可以理解成一个简单的浏览器。再通过 getinfo() 定义的定量获取 HTTP 返回结果(response),采集的数据将即时入库,异常响应将触发告警,关键代码如下:

detector/runmonitor.py
……
Curlobj = pycurl.Curl()  # 创建Curl对象
Curlobj.setopt(Curlobj.URL, url)  # 定义请求的URL
# 定义setopt请求器常量,各参数详细说明见2.4节
Curlobj.setopt(Curlobj.CONNECTTIMEOUT, CONNECTTIMEOUT)
Curlobj.setopt(Curlobj.TIMEOUT, TIMEOUT)
Curlobj.setopt(Curlobj.NOPROGRESS, 0)
Curlobj.setopt(Curlobj.FOLLOWLOCATION, 1)
Curlobj.setopt(Curlobj.MAXREDIRS, 5)
Curlobj.setopt(Curlobj.OPT_FILETIME, 1)
Curlobj.setopt(Curlobj.NOPROGRESS, 1)
bodyfile = open(os.path.dirname(os.path.realpath(__file__)) + "/_body", "wb")
Curlobj.setopt(Curlobj.WRITEDATA, bodyfile)
Curlobj.perform()
bodyfile.close()
# 定义getinfo响应返回常量,各参数详细说明见2.4节
self.NAMELOOKUP_TIME = Decimal(str(round(Curlobj.getinfo(Curlobj.NAMELOOKUP_TIME), 2)))
self.CONNECT_TIME = Decimal(str(round(Curlobj.getinfo(Curlobj.CONNECT_TIME), 2)))
self.PRETRANSFER_TIME = Decimal(str(round(Curlobj.getinfo(Curlobj.PRETRANSFER_TIME), 2)))
self.STARTTRANSFER_TIME = Decimal(str(round(Curlobj.getinfo(Curlobj.
                                                            STARTTRANSFER_TIME), 2)))
self.TOTAL_TIME = Decimal(str(round(Curlobj.getinfo(Curlobj.TOTAL_TIME), 2)))
self.HTTP_CODE = Curlobj.getinfo(Curlobj.HTTP_CODE)
……

最后,配置系统 crontab,5分钟作一次数据采集,内容如下:

*/5 * * * * /usr/bin/python /data/detector/runmonitor.py > /dev/null 2>&1

rrdtool作业

rrdtool 作业实现从 MySQL 导出数据并更新到 rrdtool 中,以便为后面的 rrdtool 报表功能提供数据支持。具体方法是通过查询 webmonitor_monitordata 表字段 MARK 为 '0' 的记录,再将数据通过 rrdtool.updatev() 方法做 rrdtool 更新,最后更新数据库标志 MARK 为 '1'。rrdtool 作业部署在任一台安装 rrdtool 模块的主机上即可,本示例的 rrdtool 作业与 Web Server 部署在同一台主机上。部分关键源码如下:

Servermonitor/webmonitor/updaterrd.py
def updateRRD(self, rowobj):  # 更新rrd文件方法
    if str(rowobj["HTTP_CODE"]) == "200":  # 非HTTP200状态标志“1”
        unavailablevalue = 0
    else:
        unavailablevalue = 1
    FID = rowobj["FID"]

    time_rrdpath = RRDPATH + '/' + str(self.getURL(FID)) + '/' + str(FID) + '_' + \
                   str(self.rrdfiletype[0]) + '.rrd'  # 指定三个特性数据rrdtool文件位置
    download_rrdpath = RRDPATH + '/' + str(self.getURL(FID)) + '/' + str(FID) + '_' + \
                       str(self.rrdfiletype[1]) + '.rrd'
    unavailable_rrdpath = RRDPATH + '/' + str(self.getURL(FID)) + '/' + str(FID) + '_' + \
                          str(self.rrdfiletype[2]) + '.rrd'

    try:  # 将查询的MySQL记录更新到rrd文件
        rrdtool.updatev(time_rrdpath, '%s:%s:%s:%s:%s:%s' % (str(rowobj["DATETIME"]) \
                       , str(rowobj["NAMELOOKUP_TIME"]), str(rowobj["CONNECT_TIME"]),str(rowobj["PRETRANSFER_TIME"]),str(rowobj["STARTTRANSFER_TIME"]),str(rowobj["TOTAL_TIME"])))
        rrdtool.updatev(download_rrdpath, '%s:%s' % (str(rowobj["DATETIME"]), \
                        str(rowobj["SPEED_DOWNLOAD"])))
        rrdtool.updatev(unavailable_rrdpath, '%s:%s' % (str(rowobj["DATETIME"]) \
                        , str(unavailablevalue)))
        self.setMARK(rowobj["ID"])  # 更新数据库标志
    except Exception as e:
        logging.error('Update rrd error:' + str(e))


def setMARK(self, _id):  # 更新已标志记录方法
    try:
        self.cursor.execute("update webmonitor_monitordata set \
            MARK='1' where ID='%s'" % (_id))
        self.conn.commit()
    except Exception as e:
        logging.error('SetMark datebase  error:' + str(e))


def getNewdata(self):  # 获取未标志的新记录方法
    try:
        self.cursor.execute("select ID,FID,NAMELOOKUP_TIME,CONNECT_TIME, PRETRANSFER_TIME, STARTTRANSFER_TIME, TOTAL_TIME, HTTP_CODE, SPEED_DOWNLOAD, DATETIME from webmonitor_monitordata where MARK = '0'")
        for row in self.cursor.fetchall():
            self.updateRRD(row)
    except Exception as e:
        logging.error('Get new database  error:' + str(e))

同目录下的 config.py 为 rrdtool 作业配置文件,定义了数据库连接信息及项目路径等信息,可根据实际情况相应修改,最后配置系统 crontab,建议与采集同一执行频率,如每 5 分钟,内容如下:

*/5 * * * * /usr/bin/python /data/www/Servermonitor/webmonitor/updaterrd.py > /
        dev/null 2>&1