(node性能优化一) API响应时间监测

jopen 8年前

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

传送 Installing on Debian / Ubuntu

1)开启服务

配置位置: /etc/grafana/grafana.ini

sudo service grafana-server start  

命令执行成功后,将在 3000 端口开启http服务,浏览器访问 http://your_ip:3000

2)添加InfluxDB支持

直接使用系统默认帐号 admin/admin 登入系统,添加 Data Sources InfluxDB 。 配置完毕后,添加一个DashBoard,按照提示选择需要呈现的数据和纬度。

后续

完成上述操作后,稍作配置就可以得到类似封面图的效果啦。

接下来

  • 针对外部服务的性能消耗统计
  • 整理一些 Grafana 针对 InfluxDB 的常用统计语句
</div>

来自: http://f2e.souche.com/blog/nodexing-neng-you-hua-apixiang-ying-shi-jian-jian-ce/