1 需求
对于一款手游来说,知道当前在线的玩家数量是十分重要的,可以做运营分析和掉人故障预警。
对于一款棋牌游戏,树状结构大致如下:
房间是基本的采集节点,在服务端程序内部可以实时统计当前房间内的玩家数。
玩法是一级汇总节点,将挂在自己节点下的房间人数加起来,就是这个玩法的人数
麻将是二级汇总节点,将挂在自己节点下的玩法人数加起来,就是这个麻将的人数
所以麻将的人数加起来,就是整个客户端的人数。
现在需要设计一个报警系统,根据一定判断策略,将一定统计周期内(比如1-2分钟)玩法的掉人邮件发送给指定邮箱(麻将级别的多个负责人)
2 表设计
首先考虑的是解耦的问题,服务端小伙伴将每个采集节点的数据实时汇报到中间件,然后监控系统过去取数据,这样彼此的开发上就是分离的。
2.1 数据获取
这里服务端提供一个web api,将所有采集节点的数据打包成一条json数据,格式如下,使用http get方法获取
{ 'timestamp':1554876185,'data': { 'roomid_1': 12, 'roomid_2': 34, 'roomid_1': 34, ... } }
2.2 数据存储
第一步要把所有roomid的数据采集并存储,这里参考zabbix的mysql表设计,每隔一个采集周期(假设1分钟),到web api获取一次数据并写入mysql。
CREATE TABLE `gameroom_sec` ( `roomid` int(8) NOT NULL, `clock` int(11) NOT NULL, `num` int(4) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
第二步做玩法级别的数据汇总,对roomid的数据汇总计算后,写入以下表
CREATE TABLE `gameid_sec` ( `gameid` int(8) NOT NULL, `clock` int(11) NOT NULL, `num` int(4) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
2.3 报警对象配置
设计一张玩法对应麻将项目的表,和麻将项目对应报警邮箱的表
CREATE TABLE `gameid` ( `id` int(8) NOT NULL, `name` varchar(64) DEFAULT NULL, `groupid` int(8) NOT NULL, `active` tinyint(1) NOT NULL DEFAULT '1', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `gamegroup` ( `id` int(8) NOT NULL, `name` varchar(64) NOT NULL, `mail` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3 采集脚本
采集脚本每隔一个采集周期,把web api的数据采集并做修改,然后写入gameroom_sec和gameid_sec表
4 监控脚本
对每个玩法做计算,将符合报警策略的玩法,调用报警模块
from smtplib import SMTP from email.header import Header from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart def mail(subject, content,mailToAddr): mailserv = mailport = mailuser = mailpwd = from_addr = to_addr = mailToAddr if to_addr != []: debuglevel = 0 smtp = SMTP() smtp.set_debuglevel(debuglevel) smtp.connect(mailserv, mailport) smtp.ehlo() smtp.starttls() smtp.ehlo() smtp.login(mailuser, mailpwd) message = MIMEMultipart() message['From'] = Header(from_addr, 'utf-8') message['To'] = Header(','.join(to_addr), 'utf-8') message['Subject'] = Header(subject, 'utf-8') mailMessageText = content message.attach(MIMEText(mailMessageText, 'plain', 'utf-8')) smtp.sendmail(from_addr, to_addr, message.as_string()) smtp.quit() #mailToAddr传进来是个包含多个邮箱地址的列表 #然后要拼接成用逗号隔开的字符串,传给Header