(node性能优化一) API响应时间监测
Written with vim
古语:“知己知彼,百战不殆”,面对性能优化,哪怕不求百战不殆,也求“死得明白”,所以在尝试进行系统性能优化之前,先得了解系统的性能瓶颈在哪,不至于使不上劲。
我不生产知识,只是知识的搬运工,都是团队实践的总结。
监控选型:Grafana + Telegraf + InfluxDB
选型是团队的架构湿安叔做的,考虑到数据实时性和灵活性,选择了 Grafana (下文简称Gra) 和 InfluxDB (下文简称Inf), 与 oneapm 互补。
- Inf是 time-series data 类型的数据库,支持类sql语句查询,适合监控数据存储,实时分析。
- Telegraf 是安装于生产机的守护进程,用于埋点数据收集并转发到Gra数据库,并收集宿主机负载信息
- Gra 用作数据呈现,封面截图就来自Gra
实践环境:
- node v4.2.3
- Ubuntu 14.04,15.04
- Express v3.4.7 ~ v4.13.3
step1:安装InfluxDB
1)下载和安装
传送 InfluxDB - Database Download ,直接找到 Ubuntu & Debian 章节,按照提示安装,相比于apt-get方法,此法在国内特殊环境下靠谱些。
2)启动:
sudo service influxdb start
3)检查服务是否启动
sudo netstat -apn | grep 8086
看到如下结果,代表启动正常
tcp6 0 0 :::8086 :::* LISTEN 1746/influxd
step2:安装Telegraf
1)下载和安装
传送 Telegraf - Data Collector Download ,通InfluxDB,按照提示安装即可。
2)配置文件
安装完成后,Linux debian and RPM packages 的配置文件位置在 /etc/opt/telegraf/telegraf.conf 打开文件后,发现 SERVICE PLUGINS 是空的,我们需要安装 statsd ,Telegraf 命令的位置在 /opt/telegraf/telegraf
执行
/opt/telegraf/telegraf -usage statsd
输出
# Statsd Server [[plugins.statsd]] # Address and port to host UDP listener on service_address = ":8125" # Delete gauges every interval (default=false) delete_gauges = false # Delete counters every interval (default=false) delete_counters = false # Delete sets every interval (default=false) delete_sets = false # Delete timings & histograms every interval (default=true) delete_timings = true # Percentiles to calculate for timing & histogram stats percentiles = [90] # templates = [ # "cpu.* measurement*" # ] # Number of UDP messages allowed to queue up, once filled, # the statsd server will start dropping packets allowed_pending_messages = 10000 # Number of timing/histogram values to track per-measurement in the # calculation of percentiles. Raising this limit increases the accuracy # of percentiles but also increases the memory usage and cpu time. percentile_limit = 1000
将配置示例复制到 SERVICE PLUGINS 下方。 statsd 允许其他应用通过udp的方式,以特定语法向Telegraf传递应用数据。3)开启服务
sudo service telegraf start
4)检查服务
sudo netstat -apn | grep 8125
输出如下,代表启动正常
udp6 0 0 :::8125 :::* 2696/telegraf
step3: 应用埋点-以 Express 为示例
应用埋点,其实就是向Telegraf的Statsd服务发送数据包,端口是8125
在需找中间件的过程中,发现了 Uber express-statsd ,README.md 内给出了一种埋点方法 传送门
推荐的方法是在路由定义时就需要确定这个API对应的Key,但是实际情况是,我参与的项目已经有几十万行的代码量,大量路由已经定义过,不可能再去动这些路由。
当时尝试的第一种方式,req.statsdKey 为 req.url,然而url是动态的,随便加个参数就不同了,会产生大量无用key,而且并没有按照API进行有效的聚合,尤其是GET类型的请求。
尝试的的第二种方式,req.path 为 key,但是碰到 path url 样式的路由就会和 req.url 发生一样的状况,例如 /get/user/:id 。
接着尝试第三种方式
先脱离Express,回到最基础 node 内置模块 http,以前我们要开启一个http服务器,会这样书写
'use strict'; var http = require('http'); http.createServer(function(req,res){ res.writeHead(200,{'Content-Type':'text/html; charset=utf-8'}); /** 中间对URL做判断,输出不同结果;判断的过程其实就是Express的route */ res.end(req.url + ' at time ' + Date.now() + ' \n'); }).listen(9002);
所以, var app = express() ,如果去看app的类型,其实就是个Function,我们在app上绑定上一堆中间件后,最后会执行这么一句
http.createServer(app).listen(PORT);
所以尝试把焦点放到 Express 的路由机制上,假设 Express 最后处理了一个请求并且有返回,那么在请求结束的时候,req 对象上应该会存有匹配到的路由的信息,因为路由信息是确定的,所以可以作为key,而且可以保证请求按照API进行聚合。
首先确定,一次请求在什么时候结束,查阅文档发现,http 模块内 的res 对象有 finish,close,error 事件,用之。
再去获取 req 对象上的路由信息,通过 debug 模式发现了 Express 在 req 对象上绑定了 route 对象,保存了请求匹配的路由信息。
综上,改写了 express-statsd-route 这个模块,具体使用方法可查看项目README。
检查埋点是否成功
Command shell 连接到InfluxDB
influx
在shell内执行
# 选择 telegraf 数据库 USE telegraf # 显示所有统计字段,检查埋点key是否存入 SHOW MEASUREMENTS
step4:安装Grafana
sudo service grafana-server start
命令执行成功后,将在 3000 端口开启http服务,浏览器访问 http://your_ip:3000
2)添加InfluxDB支持
直接使用系统默认帐号 admin/admin 登入系统,添加 Data Sources InfluxDB 。 配置完毕后,添加一个DashBoard,按照提示选择需要呈现的数据和纬度。
后续
完成上述操作后,稍作配置就可以得到类似封面图的效果啦。
接下来
- 针对外部服务的性能消耗统计
- 整理一些 Grafana 针对 InfluxDB 的常用统计语句
来自: http://f2e.souche.com/blog/nodexing-neng-you-hua-apixiang-ying-shi-jian-jian-ce/