浅谈 OneAPM 在 express 项目中的实践
【编者按】OneAPM 运营团队,近日在 github 上发现了一篇文章,特别奉献给大家。本文作者王宇先生从2015年年初就开始使用我们的产品,也是OneAPM 的忠实用户。
OneAPM 是一个优秀的性能监控平台。为什么我们要使用性能监控呢? 并不是为了炫耀我有多么酷的玩具,仅仅因为我们希望在问题发生的第一时间就能知道。 在第一时间发现问题,把问题解决于无形之中,总比出了大麻烦通宵达旦加班舒服得多。
然而有的人喜欢说:「有些问题留着也不会有什么影响。」但我觉得服务端的事情, 凡是冒烟的地方,终究会着火的。
还有的人喜欢说:「我的代码绝对不可能有 bug 。」不过这只是吹牛逼。
废话不说了,直接上干货吧。
OneAPM 的监控服务主要分以下几块
- Application Insight: 应用程序监控
- Browser Insight: 浏览器客户端监控
- Mobile Insight: 移动客户端监控
- Infrastructure Insight: 服务器监控
使用 OneAPM 监控自己的项目,首先你需要去 OneAPM.com 注册一个开发者账号。
Application Insight 应用程序监控
登录平台以后根据自己项目的语言选择探针,我这里项目是用的 express,所以选择了 nodejs, 在 OneAPM 里面对怎么安装探针写得很详细,大概就是在项目的目录下运行
npm install OneAPM --registry http://npm.OneAPM.com
然后配置文件从 node_modules/OneAPM 里面拷出来,改一下 License Key ,就这么简单。
我们安装好探针以后,过几分钟让插件收集到数据,就能在面板里面看到各种图标。
首先需要关注的是 响应时间图表
这个图表会对服务端耗时给一个大体印象,大家可以发现我们项目最慢的时候, 是发生在 8 月 18 号晚上左右,有请求大约 1.25s 才结束。紫色的占了绝大多数, 这些都是外部服务消耗的时间。
右上角的窗口叫做 apdex
这是一个评估用户满意度的指标,从这个指标可以看到用户是否满意我们的响应速度, 最右上角有 1[0.5] 可以看到我们 100% 的用户都满意我们的响应速度,小于 0.5 秒的请求, 我们称之为满意。我们这里是用的 OneAPM 的默认设置,小于 0.5 秒表示满意,0.5-2 秒是可容忍, 2秒以上则不满意。
cpm 图表
这个图表代表吞吐量
我们可以看到项目最高的时候,大概每分钟 80 次请求,平均每分钟 17.88 次请求。
web事务图表
这是一个很重要的图表,在这里我们能看到性能最差的几个 web 事务,我们通过 url, 能找到代码中对应的 controller 函数,从而找到这个接口中性能的瓶颈
我们来仔细看一个请求吧,第一条 express/POST/api/ex... (鼠标放上去可以显示全部的 url, 实际上这一条是这样的 Expressjs/POST/api/exams/signup-all)
我们可以点进去,查看接口的详细情况。
里面有一些仅对这个接口的吞吐量,执行时间等等的图表,具体含义和前面介绍的差不多 ,只不过考察的对象变成了唯一这一个接口。
我认为最重要的一个图表是 breakdown table
这个图表反应了我们这个接口对外部应用(external),数据库( database )的调用情况。 从图表上可以发现,每次我们调用这个接口,我们会调用 37 次一个叫做 xxxxxtct.com 是 http 协议的 外部服务。执行的时间占到了 96.88%,另外查了 2 次数据库。分别占 0.49% 和 0.07%
看到这里,咱们就知道怎么优化啦~~拿我这个接口来说,这里的瓶颈主要是卡在发送 37 次 http 请求给 xxxxxtct.com 这个地方,这个 xxxxxtct.com 其实是我们自己的一个子系统,如果我在子系统里面写一个接口,把现在 37 个请求的内容合并,这个性能问题就完美的解决了。
另外 OneAPM 的 Application Insight 还给我们提供了,系统拓扑图,按 web 事务查找瓶颈的功能,按 sql 查找瓶颈的功能, 外部服务的具体执行时间(这个很重要,看谁在拖我们的后腿)以及后台服务的监控。
最后说一下错误率这个 table,这是我个人的经验
express 在抛出系统异常的时候,有可能会挂掉。下面举2个栗子
exports.show = function(req, res) {
a.b //a == undefined
}
抛出异常
exports.show = function(req, res) {
request.post({
url: xxx-service.com
}, function(err, response, body) {
a.b //a == undefined
})
}
抛出异常,然后服务挂掉。
OneAPM 是被 express 程序启起来的,算是 express 进程的一个子进程,如果 express 挂掉了, OneAPM 也跟着挂了,所以,不可能有机会发回错误信息。 结论是只要在回调里面抛出的异常,任何探针都没有办法收集到错误, 因为在这一层无法做这件事情。
当然,我们虽然有 pm2 这样优秀的进程管理工具来帮我们,挂掉之后自动重启服务。。。 但我们需要在第一时间获得报错信息啊。。。。即使 pm2 的 errpr.log 里面会保留异常, 但谁又会没事专门盯着 error 这个日志看呢。
针对这个问题,我自己写了一段代码来收集错误日志,希望对大家有帮助。
var pm2 = require('pm2');
var Slack = require('slack-node');
pm2.launchBus(function(err, bus) {
console.log('connected');
bus.on('log:err', function(data) {
var webhookUri = "{你的slack webhook}";
var slack = new Slack();
slack.setWebhook(webhookUri);
slack.webhook({
channel: "#general",
username: "cq-tct",
icon_emoji: ":ghost:",
text: data.data
}, function(err, response) {
console.log(response);
});
});
});
把这一段保存为 err_notifier.js 放在项目根目录下,每次启完服务之后运行
node err_notifier.js 这样就能通过 slack 第一时间收到报错了。即使服务挂掉也能发过来。
这里用了另一个叫做 slack 的工具,slack 是一款即时通信的办公协作工具,相信大家或多或少都听说过 (就是创业半年估值 11 亿美元,一年变 28 亿那个家伙)。国外类似的还有 hipchat, 国内我不太清楚。
首先去 slack 申请一个 team, 然后创建一个 room,为 room 打开一个 webhook, 把 webhook 的地址赋值给 webhookUri, 这样我们无论在哪里,只要项目报错,就能第一时间 收到通过 slack 推送过来的错误日志。
当然,你可以把推送的工具改成,hipchat,邮件,短信,这个随大家高兴了。 关于 pm2 的 event monitor,还有更多事情可做,大家可以参考这里
最后
OneAPM 虽然可以帮大家在开发初期铺平道路,但也不意味着因为有了监控就可以胡作非为 (反正项目只要冒烟了,OneAPM 一目了然)。
我认为最靠谱的做法是: 严格遵守各种 style guide 来写代码 + 一个监控系统 + 100% 覆盖率的单元测试 + 几套集成测试 + 一套可靠的发布流程。
写在最后:OneAPM 非常感谢王宇先生对我们产品的支持,未来我们将更加努力,为用户提供更大的价值。
浅谈 OneAPM 在 express 项目中的实践的更多相关文章
- 浅谈 Axios 在 Vue 项目中的使用
介绍 Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中. 特性 它主要有如下特性: 浏览器端发起XMLHttpRequests请求 Node端发起http ...
- 转:浅谈CSS在前端优化中一些值得注意的关键点
前端优化工作中要考虑的元素多种多样,而合理地使用CSS脚本可以在很大程度上优化页面的加载性能,以下我们就来浅谈CSS在前端优化中一些值得注意的关键点: 当谈到Web的“高性能”时,很多人想到的是页面加 ...
- Mongo基础使用,以及在Express项目中使用Mongoose
MongoDB的基本使用 MongoDB特点: 使用BSON存储数据 支持相对丰富的查询操作(相对其他nosql数据库) 支持索引 副本集(支持多个实例/多个服务器运行同个数据库) 分片(数据库水平扩 ...
- 浅谈Python在信息学竞赛中的运用及Python的基本用法
浅谈Python在信息学竞赛中的运用及Python的基本用法 前言 众所周知,Python是一种非常实用的语言.但是由于其运算时的低效和解释型编译,在信息学竞赛中并不用于完成算法程序.但正如LRJ在& ...
- 【WebApi系列】浅谈HTTP在WebApi开发中的运用
WebApi系列文章 [01]浅谈HTTP在WebApi开发中的运用 [02]聊聊WebApi体系结构 [03]详解WebApi参数的传递 [04]详解WebApi测试和PostMan [05]浅谈W ...
- 在express项目中使用formidable & multiparty实现文件上传
安装 formidable,multiparty 模块 npm install formidable,multiparty –save -d 表单上传 <form id="addFor ...
- 在express项目中使用redis
在express项目中使用redis 准备工作 安装redis 安装redis桌面管理工具:Redis Desktop Manager 项目中安装redis:npm install redis 开始使 ...
- Immutable.js 以及在 react+redux 项目中的实践
来自一位美团大牛的分享,相信可以帮助到你. 原文链接:https://juejin.im/post/5948985ea0bb9f006bed7472?utm_source=tuicool&ut ...
- TypeScript在react项目中的实践
前段时间有写过一个TypeScript在node项目中的实践. 在里边有解释了为什么要使用TS,以及在Node中的一个项目结构是怎样的. 但是那仅仅是一个纯接口项目,碰巧赶上近期的另一个项目重构也由我 ...
随机推荐
- Ajax-goahead局部刷新页面
软件开发最常用的方法是:C/S,B/S.如果嵌入式设备中使用Ajax,那么既可以使用C/S方式,也可以使用B/S开发上位机.最近公司的一个项目需要异步获取后台数据,使用form更新数据时会有空白卡顿不 ...
- 解惑:NFC手机如何轻松读取银行卡信息?
自支付宝钱包8.0推出了NFC新功能,只要将支持NFC功能的手机靠近公交卡.银行卡等带有芯片的IC卡上,可迅速读取卡内余额.卡的信息,还可以给卡进行充值,非常贴心实用. 但是很多网友表示担忧,要是别人 ...
- Android之Activity的几种跳转方式
1.显示调用方法 Intent intent=new Intent(this,OtherActivity.class); //方法1 Intent intent2=new Intent(); in ...
- 通过Roslyn构建自己的C#脚本
通过Roslyn构建自己的C#脚本 在下一代的C#中,一个重要的特性就是"Compiler as a Service",简单的讲,就是就是将编译器开放为一种可在代码中调用的服务.最 ...
- 取精华、去糟粕!适合iOS开发者的15大网站推荐
iOS开发者若想使技艺达到炉火纯青的地步,就要不断借鉴他人的有益经验,紧跟新兴科技和工具的步伐.除了Apple的开发者中心,其他网站上的文章和资源也具备参考价值,若能学得一二,必能锦上添花.不过,时间 ...
- Window7上搭建symfony开发环境(PEAR)
http://blog.csdn.net/kunshan_shenbin/article/details/7162243 1. 更新PEAR 进入PHP所在目录,找到go-pear.bat并双击. 一 ...
- .net(C#)操作文件的几种方法汇总
.net(C#)操作文件的几种方法汇总 System.IO命名空间下类的用法:在System.IO名称空间中包含了用于文件输入输出的主要类.File:实用类,提供许多静态方法,用于移动.复制和删除文件 ...
- 初识MVC,MVC里面的基本数据传递
MVC是一种表现形式,他将Web应用程序分成三个组件即:视图(View)控制器(Controller)模型(Model). M:Model 主要是存储或者是处理数据的组件 V:View 是 ...
- ASP.NET Web API 入门大杂烩
[前言] 本文是大杂烩,意思即是:到处Copy再加一点点思考而混在一起的文章,引用来源因为太多太杂故而省略,望原作者原谅. [概述] ASP.NET Web API随ASP.NET MVC 4一起发行 ...
- C++中的抽象类及纯虚函数的实现与否
1.含有纯虚函数的叫抽象类 2.抽象类(一般是基类)中的纯虚函数无论函数体实现与否,都没有关系,系统会自动忽略 3.继承自抽象类的子类,必须要实现父类的纯虚函数才可以实例化对象 4.抽象类不允许实例化 ...