系统环境部署
数据采集角色
数据采集功能角色需要完成两个任务:一为采集远程业务服务集群 HTTP 响应数据,并将数据写入远程 MySQL 数据库;二为提供异常 HTTP 响应告警支持。本示例部署 192.168.1.20、192.168.1.21 主机,分别模拟电信与联通网络。下面详细说明。
数据采集端只有两个 Python 文件,一个为 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),采集的数据将即时入库,异常响应将触发告警,关键代码如下:
……
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 部署在同一台主机上。部分关键源码如下:
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