线上监控目的
- 尽早的发现线上问题
- 当前 的异常情况。
- 一段时间内 的异常情况。
各种各样的监控
机器、服务情况、业务等等
不同种类的监控一般实施人员会有区别
- 运维、云平台服务提供商
- 开发
- 测试
运维一般做业务无关的监控,主要是 机器、容器 相关,同时也可能包括一些服务(进程)的 死活 监控等等。
一个活着的服务是不是提供了 可用的服务 ,则一般由开发来做。(不绝对)
开发和测试在这方面 并没有明确的界限 ,一般会有一个分工,以免产生重复劳动。
具体需要做哪些监控,取决于 实际的需求。
- 机器
- 存活、CPU、内存、硬盘、带宽等等
- 服务
- 进程存活、数量正确,等等
- 是否正常响应
- HTTP 接口(通过实时请求检查返回的 header 、 body)
- 是否 200 或符合预期的 301 / 302 等
- errno 是否未 0 或者符合预期的其他错误码
- header 中关键字段是否正确
- Location
- Set-cookie
- Content-Type
- 等
- body 中字段是否正确
- 根据需要对比数据库或其他存储介质
- 响应时间
- 页面UI(一般通过 模拟浏览器 行为来校验 dom或截图)
- header 部分同 HTTP 接口
- 页面元素是否存在或者样式是否正确
- 日志(从各机器采集日志来进行统计分析)
- 4xx/5xx 一段时间内数量
- 请求量( 激增 或 暴跌 )
- 平均响应时间
- 业务日志报错情况( 提前日志输出 )
- 业务
- 日志和数据库(或其他存储介质)是否一致
- 各个存储介质之间数据一致性
- 如订单与商品
- 某些业务量的 激增 或 暴跌
- 竞品 / 第三方
- 新上架的商品
- 价格变化
- 排行榜
主要的流程
- 采集
- 接口请求、日志拉取等
- 校验 / 统计
- 检查是否需要报警
- 单词/连续失败
- 一段时间内失败次数
- 数量激增或暴跌
- 数据不一致
- 报警
- 短信、邮件、微信等
- 存储
- 作为长期分析使用
目前的工作
接口监控、日志监控、页面元素监控(待完成)
使用 nodejs 进行编写
目录结构(参看代码)
- ylwlib // 存放自写的基础库和配置
- config.js // 配置文件,包括邮件、部分阈值等等
- req.js // HTTP 请求封装
- mail.js // 发邮件
- sms.js // 发短信
- util.js // 一些公共方法,校验之类的
- apimon // 接口监控
- apimon.js // 单个 case 文件执行用
- runApiMon.js // 所有 case 执行的管理入口
- cases // 目录,存放各种 case 文件
- var // 运行中需要的数据文件存放
- logmon // 日志监控
- logmon.js // 日志监控执行文件
- logmonCases.js // 日志监控各阈值配置文件
- uimon // UI 监控(待完成)
有关执行
- 目前在测试机上执行, 由 crontab 维护
- 日志监控每小时执行一次
- 接口监控每分钟执行一次
- 目前是串行,后续可以根据情况改成并行
-
日志监控每次执行的时候,会进行 git pull , 意味着日常只要提交 git ,就能保证下次监控使用最新的 case 列表。不需要再去调整已经部署完毕的监控框架。
- 一些小逻辑
- 考虑到执行时间暂时不可控(比如超过1分钟),都有 lock 文件。
- 同时为了避免某些异常导致 lock 文件不被清除,都有 过期失效 逻辑。
- 有关接口监控的报警阈值,目前是两个控制逻辑
- 连续报警(目前是连续2次)
- 最近N次成功失败记录
- 当次失败(未达到连续报警阈值)
- 最近 N 次记录中,失败率达到 M% 的,认为不稳定,也会报警。
有关接口监控报警文案
- 邮件,会另附上 URL 地址
- 短信不含 URL 地址
- IP详情页(奶爸宣言) get_Chrome_producer: network FAILED
- IP详情页(奶爸宣言) get_Chrome_producer: objId校验 FAILED
- URL描述 + get/post + UA + user[nologin/nopower/author/producer] + 检查项描述 + FAILED
- network 表示网络问题,比如自身网络失败,或者域名不可解析
- 其他项基本都是 case 中配置的
- 所以写 case 的时候,需要用简单文案表达清楚 监控的事项
日志监控配置简单说明
直接参考文件 logmonCases.js
接口监控 Case 说明
部署路径
apimon/cases
目前是按照 yunlaiwu.com 的前缀 m/user/api/www 来区分的目录,实际不影响任何监控功能。 目录可以按照需要来部署。
文件名举例
sns_user_info.js
最好按照 url 的路径来取名,方面查阅。 一定要 .js 结尾,同时 符合 js 语法。
case 编写举例
'use strict';
/**
* <必填> list cases 本身是个 list, 每个 item 根据 不同 情况, 如不同 请求参数区分。
*/
var cases = [
{
// <必填> string url: url 地址, 可以是接口或者页面。
url: 'https://api.yunlaiwu.com/sns/user/info?uid=57b4213a165abd0065c7ad54',
// <选填> object qs: querystring, 可以直接放 url 里
// qs: {uid: '57b4213a165abd0065c7ad54'},
// <选填> object form: 给 post 用的提交参数。
// form:
// <选填> list<string> ua: 元素为 ylwlib/config.js 里的 userAgentList 的 key 。不填时,默认执行 ['Chrome']
ua: ['Chrome', 'iOS'],
// <选填> list<string> method: 元素为 get 或 post , 不填时,默认执行 ['get']
method: ['get'],
// <选填> list<string> method: 元素为 ylwlib/userlist.online 里 的 key, 未登录情况填 'nologin'。不填时,默认执行 ['nologin']
user: ['nologin', 'producer'], // 元素为
// <必填> string desc: 描述,报警时描述使用。
desc: '用户信息接口',
// <选填> bool followRedirect: 遇到 302 等跳转是否跟随跳转,默认是 true。 为 false 时, 302 将不会继续请求 location。
// followRedirect: true,
// <选填> object check: 需要检查的项。 不填时,默认校验 statusCode 是否为 200。
check: {
// <选填> string statusCode: 返回码, 一般是 200, 有些情况下可能是 302, 或其他。
statusCode: 200,
// <选填> string errnoKey: 接口里用来标示 errno 的 key,一般是 errno,某些时候可能 code,不填则不校验。(页面没必要填)
errnoKey: 'errno',
// <选填> list<object> funcs: 自定义的校验方法列表。
funcs: [
{
// <必填> string desc: 描述,报警时描述使用。
desc: 'objId校验',
// <必填> function func: 自定义的校验方法。 入参固定为 ({headers, body}) 用法简单如下,headers 里的参数可以自行打印查看。
// 请务必在成功时返回 true, 失败是返回 false, 否则可能影响监控。
func: function ({headers, body}) {
try {
// 转成 对象
var body = body;
if (typeof body != 'object') {
body = JSON.parse(body);
}
if (body.data.objectId == '57b4213a165abd0065c7ad54') {
return true;
}
} catch (e) {
return false;
}
return false;
}
},
]
}
},
];
// <必填> 通用写法,勿改动,请照抄
module.exports = {
cases: cases,
}
日常增加新的 case 之后, 可以本地调试。
有关一些本地调试相关的事情在 README 上有说明 https://github.com/yunlaiwu/ylwautotest
后续工作
- UI监控的加入
- 使用 phantomjs 作为组件
- 目前主逻辑能跑通,具体的监控逻辑尚未完成
- 相关同学也可以尝试对新接口、页面进行自己的补充
- 如有必要( 请确保代码无误 ),也可以对框架本身代码进行维护
- 谢谢 ^_^