cheniu-api-time-line.png 古语:“知己知彼,百战不殆”,面对性能优化,哪怕不求百战不殆,也求“死得明白”,所以在尝试进行系统性能优化之前,先得了解系统的性能瓶颈在哪,不至于使不上劲。

我不生产知识,只是知识的搬运工,都是团队实践的总结。

监控选型: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 的常用统计语句

results matching ""

    No results matching ""