https://github.com/xieguigang/linux-profiler

废话不多说,首先给出一个 demo报告链接 给大家看看这个小工具的成品输出。

在去年的工作中,因为公司需要购买新的服务器做集群计算,需要一个工具来记录之前的服务器在数据分析上的性能瓶颈。于是花了两天的时间赶出来了这个专门应用于Linux系统的性能记录工具。这个小工具是一个开源项目,大家可以在Github上阅读这个开源项目(linux-profiler)的源代码

这个性能测试用的帮助小工具,在里面分为两部分构成:性能计数器和性能报告模块。这在里我分别针对这两个模块组件进行项目开发说明。

性能计数器

这个性能测试小工具的最主要的一个功能就是记录在执行数据分析程序的时候系统运行的每一个状态。对于一个系统运行状态,其就是某一个时间点上我们对系统的各个状态文件的内容进行一次快照储存。当我们对足够多的时间点的状态进行快照储存之后,就可以得到整个系统的性能记录数据了。

所以在这个小工具里,我们定义了一个Snapshot对象,用来储存某一个时间点上的系统性能快照,例如内存使用率,CPU使用率,硬盘IO速度等信息。

Public Class Snapshot

    Public Property uptime As uptime
    Public Property timestamp As Double
    Public Property mpstat As mpstat()
    Public Property free As free
    Public Property iostat As iostat
    Public Property ps As ps()

    Public Function FindAllCPUUsage() As Double
        Return mpstat _
            .Where(Function(a) a.CPU <> "all") _
            .Sum(Function(cpu)
                Return cpu.gnice +
                       cpu.guest +
                       cpu.iowait +
                       cpu.irq +
                       cpu.nice +
                       cpu.soft +
                       cpu.steal +
                       cpu.sys +
                       cpu.usr
            End Function)
    End Function

    Public Overrides Function ToString() As String
        Return uptime.ToString & ", top: " & ps _
            .OrderByDescending(Function(a) a.CPU) _
            .First _
            .COMMAND
    End Function
End Class

然后我们在Profiler模块之中,不断的对系统进行状态快照采样,就可以了。下面我们来具体的聊聊在这个小工具中具体采样的系统性能数据吧:

1. CPU利用率

根据ps命令,我们可以得到每一个时间点上的所执行的进程的列表快照。在性能报告中的CPU利用率的信息数据,就是将每一个时间点的进程快照的CPU使用率都加起来就OK了。

2. 内存利用率

由于ps命令得到的内存利用信息都是百分比数据,我们通过ps命令得到实际的内存使用量比较困难。所以在这个性能小工具中,我是通过free命令来获取得到内存的实际使用量的信息。

通过free命令我们一般是可以得到每一个时刻上的内存的剩余量,以及swap的剩余量。具体的命令输出解析代码,大家可以阅读free命令模块的源代码。

3. 硬盘I/O

对于硬盘IO的速率,这个相比于CPU利用率信息和内存利用率信息的获取相对麻烦了一些。这是因为在小工具中,我是通过iostat命令来得到的。麻烦点就在于使用iostat命令我们一般可以得到每一个快照的时间点上的硬盘的总的数据读取量以及数据总的写入量。所以如果需要得到当前时间点的IO速率,我们需要对每一帧快照数据做滑窗,然后用后一个时间点的IO总量减掉前一个时间点的IO总量,得到的差值除上快照时间间隔长度才可以得到IO的速率。

下面的代码就是在小工具中进行IO速率计算用到的计算函数,大家可以参考一下:

<Extension>
Private Function IoSpeed(time2 As Snapshot, time1 As Snapshot, isRead As Boolean) As Double
    Dim t2 = DateTimeHelper.FromUnixTimeStamp(time2.timestamp)
    Dim t1 = DateTimeHelper.FromUnixTimeStamp(time1.timestamp)
    Dim dt As Double = (t2 - t1).TotalSeconds
    Dim data2, data1 As Double

    If isRead Then
        data2 = Aggregate dev As iodev In time2.iostat.devices Into Sum(dev.kB_read)
        data1 = Aggregate dev As iodev In time1.iostat.devices Into Sum(dev.kB_read)
    Else
        data2 = Aggregate dev As iodev In time2.iostat.devices Into Sum(dev.kB_wrtn)
        data1 = Aggregate dev As iodev In time1.iostat.devices Into Sum(dev.kB_wrtn)
    End If

    Return (data2 - data1) / dt
End Function

4. 系统负载

最后呢,最后一个需要进行采样的主要的性能指标就是上面所提到的性能指标的综合计算结果system load了。理论上我们是可以直接通过代码,基于上面所提到的性能数据计算出system load值的。但是由于我不太清楚这个计算公式,所以在小工具里面我就直接使用uptime命令得到快照的时间点上的系统负载值。

性能报告

在通过上面所介绍的一些命令得到系统的性能快照之后,我们就需要对得到的快照帧数据进行整合导出为可以阅读的html报告。

在性能报告模块中,我在小工具中主要是生成存储对应的数据的js文件。为什么不是生成的json文件?这个主要是因为所导出来的html报告并不是放到网页服务器上供用户阅读的,报告的html文件而是直接作为本地文件在浏览器打开。因为是通过作为一个本地文件打开,所以在浏览器中不可避免的肯定会在通过ajax加载JSON文件的时候出现跨域问题。

因为并不想将所有的东西都填充到html文件之中,所以就选择通过生成js文件来避免这个数据加载的时候的跨域问题了。

存储数据的JS文件

存储服务器的性能快照的JS文件,我都存放在了报告的根文件夹下的data文件夹。如果大家通过谷歌浏览器打开这个小工具所生成的报告html文件,按下F12打开控制台查看网络活动,可以看到加载了这几个js数据文件:

  • data/cpuinfo.js 存储CPU的硬件信息
  • data/dmidecode.js 存储系统的所有硬件信息
  • data/overviews.js 存储系统资源利用率的总览信息
  • data/ps.js 存储了每一个快照时间点上所有正在执行的进程列表
  • data/system_load.js 存储系统负载的信息

对于这些数据的js文件的生成,全都是按照js函数返回一个json对象的格式产生的,具体的生成代码,大家可以查看RunReportHandler模块中的函数代码。

<Extension>
Private Function dataJs(Of T)(data As T, name As String) As String
    Return $"
/**
 * @data {GetType(T).FullName}
 * @assembly {GetType(T).Assembly.FullName}
 * @dll {GetType(T).Assembly.Location.FileName}
*/
function {name}() {{
    return {data.GetJson(knownTypes:={GetType(String), GetType(Double())})};
}}"
End Function

数据可视化

那有了上面的存储数据的js文件之后,我们就可以使用highcharts.js进行性能数据的可视化了。我们将每一个时间点的性能统计数据对时间点作图,就可以得到系统的性能曲线,也可以使用highcharts.js显示出每一个快照时间点上的进程间的CPU利用率的分布到一个饼图。使用highcharts.js进行对应的数据可视化,大家可以上highcharts.js的官网,阅读和修改相关的demo教程代码,就可以很轻松的实现了。

在这个Linux系统的性能测试小工具中,我是使用typescript语言进行对应的html的app的编写。由于数据可视化的html报告模块是和小工具的主体相互独立的。所以大家只需要按照指定的格式生成对应的js数据文件,就可以使用这个小工具的html报告来显示你自己的性能测试小工具的结果数据啦,很方便吧。

工具的系统兼容性

这个小工具最开始是针对CentOS7开发的,后面随着运行环境的迁移,慢慢的增加了对CentOS8以及Ubuntu服务器系统的支持。目前的对这个小工具的运行测试结果看来,这个小工具在CentOS和Ubuntu这两个版本的系统之间的兼容性上已经没有任何问题了的。

根据目前的测试看来,我们所使用到的不同版本的Linux系统之间的命令工具的输出都是一样的格式,差异仅仅是在对于系统版本信息的采集所需要进行读取的文件的路径上。

例如对于CentOS系统,一般是读取的/etc/centos-release,Ubuntu系统则是读取的/etc/redhat-release文件。具体的处理代码大家可以查看Interaction.release这个只读属性的定义。

Latest posts by xie guigang (see all)

Attachments

No responses yet

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注