Java 运行时监控第 3 部分监控应用程序生态系统的性.docx
- 文档编号:28799144
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:84
- 大小:691.26KB
Java 运行时监控第 3 部分监控应用程序生态系统的性.docx
《Java 运行时监控第 3 部分监控应用程序生态系统的性.docx》由会员分享,可在线阅读,更多相关《Java 运行时监控第 3 部分监控应用程序生态系统的性.docx(84页珍藏版)》请在冰豆网上搜索。
Java运行时监控第3部分监控应用程序生态系统的性
Java运行时监控,第3部分:
监控应用程序生态系统的性能与可用性
在本系列(共三篇文章)的第1部分和第2部分中,我介绍了监控Java应用程序的技巧和模式,在这两部分中我把重点放在了JVM和应用程序类上。
在这最后一期中,我将介绍从应用程序的依赖项(诸如底层操作系统、网络或者应用程序的后端数据库)收集性能与可用性数据的技巧。
在文章结尾我将论述管理收集数据的模式以及报告和可视化数据的方法。
基于Spring的收集器
在第2部分中,我实现了一个用于管理监控服务的基本的基于Spring的组件模型。
该模型的基本原理及益处有:
∙使用基于XML的配置,使得管理大量用于配置更复杂性能数据收集器的参数集变得更加容易。
∙采用关注点分离的结构,这样就可以使用更简单的组件,这些组件之间的相互交互可以通过注入Spring的依赖项来实现。
∙Spring给简单的收集bean提供了一个生命周期,该周期由初始化、启动和停止操作组成,还提供了将Java管理扩展(JavaManagementExtension,JMX)管理接口公开给bean的选项,这样就可以在运行时进行控制、监控和故障排除。
下面我将在本文的每个小节中介绍有关基于Spring的收集器的更多细节。
监控主机和操作系统
Java应用程序总是运行于底层硬件和支持JVM的操作系统之上。
一个全面的监控基础设施中最关键的组成就是从硬件和OS—通常是通过OS收集—那里收集性能、健康状况和可用性指标的能力。
本节就涵盖了一些通过在第1部分中介绍的ITracer类获取这类数据并一直跟踪到应用程序性能管理系统(applicationperformancemanagement,APM)的技巧。
典型的OS性能指标
下面这份摘要列出了典型指标,这些指标跨域操作系统的多个部分相关。
虽然数据收集的细节迥异,而且数据的解释也必须在给定的OS上下文中进行,但是这些指标在大多数标准主机上基本都是等效的:
∙CPU使用:
表示特定主机上的CPU的占用情况。
单位通常为百分比的使用率,在较低的级别将CPU忙碌时间表示为消逝的时钟时间的某个特定时期的百分比。
主机可以有多个CPU,而CPU又可以包含多个内核,但多个内核通常都被OS抽象出来代表一个CPU。
例如,一个带有两个双核CPU的主机会被说成有四个CPU。
指标通常可以按照每个CPU收集或者作为总资源利用率收集,后者表示所有处理器的总体使用情况。
到底是要分别监控每一个CPU还是监控总体CPU,通常要取决于软件的本质及其内部架构。
标准的多线程Java应用程序通常默认平衡所有CPU上的负载,所以监控总体较合适。
但在某些情况下,个别OS进程是“特定于”特定CPU的,这时总体指标可能无法捕获到适当级别的粒度。
CPU的使用通常被拆分成四个范畴:
o系统:
执行系统的或者OS内核级的活动耗费的处理器时间
o用户:
执行用户活动耗费的处理器时间
oI/O等待:
处于空闲状态等待完成某个I/O请求耗费的处理器时间
o空闲:
暗指没有进行任何处理器活动
另外两个相关指标为运行队列长度(即等候CPU时间的请求的待处理事项)和上下文转换(即将处理器时间分配从一个进程转换到另一个进程的实例)。
∙内存:
最简单的内存指标为可用或使用中的物理内存的百分比。
其他需要考虑的有虚拟内存、内存分配率和重新分配率以及表明内存有哪些区域被使用的更细粒度的指标。
∙磁盘与I/O:
磁盘指标为每一个逻辑或物理磁盘设备的可用或使用中的磁盘空间的简单(但是至关重要的)报告,还有这些设备的读取和写入速率。
∙网络:
指网络接口上的数据传输速率和错误发生率,它通常被分为高级的网络协议范畴,如TCP和IP。
∙进程与进程组:
可以说前面所述的指标都是特定主机的总活动。
它们也可以划分为相同的指标,但是代表个别进程或相关进程组的消耗或活动。
监控进程对资源的使用情况有助于解释主机上的每一个应用程序或者服务消耗的资源比例。
有些应用程序只可以实例化一个进程;在其他情况下,一个诸如Apache2WebServer这样的服务可以实例化代表一个逻辑服务的一群进程。
代理与无代理
不同的OS有着不同的性能数据获取机制。
我将呈现的收集数据的方式很多,但是在监控领域您可能经常要区别的是基于代理的和无代理的监控。
也就是说在某些情况下,无需在目标主机上安装其他特定的软件也可以收集数据。
但显然监控通常都会涉及到某种代理,因为监控总是需要一个接口,数据要通过它来读取。
所以这里真正区别的是是使用通常出现在给定OS中的代理—诸如Linux®服务器上的SSH—还是安装其他专用于监控和使收集的数据对外部收集器可用的软件。
两种方法都涉及到如下的权衡标准:
∙代理需要安装其他的软件并可能需要应用定期的维护补丁。
在带有大量主机的环境中,管理软件工作不利于使用代理。
∙如果代理实际上是与应用程序相同的进程的一部分的话,哪怕它是一个单独的进程,代理进程的故障也将会蒙蔽监控。
虽然主机本身仍在运行且健康状况良好,但是APM一定会因为无法到达代理而假定主机已停机。
∙安装在主机上的代理可能要比无代理远程监控器的数据收集能力和事件监听能力强得多。
而且,报告总体指标可能需要收集好几个原始底层指标,远程收集这些指标的效率会很低。
而本地的代理则能够快速地收集数据,再合计数据,然后将合计的数据提供给远程监控器。
归根结底,最佳的解决方案可能就是既实现无代理的监控又实现基于代理的监控:
本地代理负责收集大多数指标,而远程监控器负责检查诸如服务器的运行情况和本地代理的状态这样的基本内容。
代理也可以有不同的选项。
自治代理按照自己的计划收集数据,反之,响应代理按请求递送数据。
此外,有些代理只将数据提供给请求程序,而有些则直接或间接地跟踪数据一直到APM系统。
接下来我将呈现监控带有Linux和UNIX®OS的主机的技巧。
监控Linux和UNIX主机
监控代理可以用来实现专门的本机库以从Linux和UNIXOS收集性能数据。
但是Linux和大多数UNIX变体都有很多内置数据收集工具,这些工具使得数据可以通过称为/proc的虚拟文件系统进行访问。
该文件看起来像是普通文件系统目录里面的普通文本文件,但其实它们是常驻内存型数据结构,是通过文本文件抽取的。
由于这种数据可以很容易地通过大量标准命令行的实用工具或自定义的工具来读取和解析,所以这些文件较易于使用,而且它们的输出既可以是通用的也可以是专用的。
而且它们的性能也非常好,因为本质上它们是直接来源于内存的数据。
常见的用于从/proc中抽取性能数据的工具是ps、sar、iostat和vmstat(参见参考资料查阅有关这些工具的参考文献)。
因此,一个有效地监控Linux和UNIX主机的方法就是执行shell命令并解析响应。
类似的监控器可以用于很多种Linux和UNIX实现;虽然它们之间都有着些许差异,但是,使用一种可以完全重用收集过程的方式格式化数据是很简单的。
相反,专用的本机库可能要根据每一个Linux和UNIX发行版而进行重编码或重构(但它们正在读取的/proc数据有可能相同)。
而编写专用于监控某一特定情况或可以标准化返回数据的格式这样的自定义shell命令很容易,并且开销较低。
现在我将展示几种调用shell命令和跟踪返回数据的方法。
Shell命令的执行
要在一个Linux主机上执行数据收集监控,就一定要调用一个shell。
它可以是bash、csh、ksh或其他任何允许调用目标脚本或命令并可以检索输出的、受支持的shell。
最通常的选择包括:
∙本地shell:
如果目标主机上运行着JVM的话,那么线程可以通过调用java.lang.Process来访问这种shell。
∙远程Telnet或ρση:
这两个服务都允许调用shell和shell命令,但由于它们的安全性相对较低,所以很少使用它们。
它们在大多数现代发行版上的默认状态为禁用。
∙安全Shell(SSH):
SSH是最为常用的远程shell。
它提供了对Linuxshell的完全访问,而且被公认是安全的。
在文中基于Shell的例子里,我将主要使用该机制。
大多数OS都提供SSH服务,包括所有UNIX系列、Microsoft®Windows®、OS/400及z/OS。
图1展示了本地shell与远程shell的基本差异:
图1.本地shell与远程shell
要用服务器启动一个无人值守的对话需要进行一些设置。
首先必须要创建一个由私钥和公钥组成的SSH密匙对。
然后将公钥置于目标服务器,私钥置于远程监控服务器——数据收集器可以在此获取该私钥。
完成上述操作之后,数据收集器便能够提供私钥及其密码短语(passphrase),并能够访问目标服务器上的安全远程shell了。
使用了密匙对之后,目标帐户的密码就是多余的了,根本不需要它。
具体设置步骤如下:
1.确保目标主机在本地的已知主机的文件中有入口。
这个文件列出了已知IP地址或名称以及为每一个已知IP地址或名称验证的相关SSH公钥。
在用户级别,该文件通常为用户主目录中的~/.ssh/known_hosts文件。
2.用监控帐户(例如,monitoruser)连接到目标服务器。
3.在主目录中创建一个名为 .ssh的子目录。
4.将目录改为e.ssh目录并发布ssh-keygen-tdsa命令。
该命令提示密钥名和密码短语。
然后会生成两个叫做monitoruser_dsa(私钥)和monitoruser._dsa.pub(公钥)的文件。
5.将私钥复制到一个安全的可访问的位置,数据收集器将从这个位置运行。
6.用catmonitoruser_dsa.pub>>authorized_keys命令将私钥内容追加到.ssh目录中名为authorized_keys的文件中。
清单1展示了我刚才所描述的过程:
清单1.创建一个SSH密匙对
whitehen@whitehen-desktop:
~$mkdir.ssh
whitehen@whitehen-desktop:
~$cd.ssh
whitehen@whitehen-desktop:
~/.ssh$ssh-keygen-tdsa
Generatingpublic/privatedsakeypair.
Enterfileinwhichtosavethekey(/home/whitehen/.ssh/id_dsa:
whitehen_dsa
Enterpassphrase(emptyfornopassphrase:
Entersamepassphraseagain:
Youridentificationhasbeensavedinwhitehen_dsa.
Yourpublickeyhasbeensavedinwhitehen_dsa.pub.
Thekeyfingerprintis:
46:
cd:
d4:
e4:
b1:
28:
d0:
41:
f3:
ea:
3b:
8a:
74:
cb:
57:
e5whitehen@whitehen-desktop
whitehen@whitehen-desktop:
~/.ssh$catwhitehen_dsa.pub>>authorized_keys
whitehen@whitehen-desktop:
~/.ssh$
现在数据收集器已经能够使用SSH连接到目标Linux主机,该SSH连接名为whitehen-desktop,它运行着UbuntuLinux。
这个例子的数据收集器将使用一个名为org.runtimemonitoring.spring.collectors.shell.ShellCollector的通用收集器类来实现。
该类的一个实例将以UbuntuDesktopRemoteShellCollector这个名称部署在一个Spring上下文中。
但要完成整个过程还需要一些其他的依赖项:
∙需要有一个调度器来每分钟调用一次收集器。
该调度器由java.util.concurrent.ScheduledThreadPoolExeutor的一个实例来实现,它既可以提供一个有计划的回调机制,又可以提供一个线程池。
这个调度器将以CollectionScheduler这个名称部署于Spring。
∙SSHshell实现对服务器调用命令并返回结果。
这个可以通过org.runtimemonitoring.spring.collectors.shell.ssh.JSchRemoteShell的一个实例来实现。
这个类是一个名为org.runtimemonitoring.spring.collectors.shell.IRemoteShell的Shell接口的实现,它将以UbuntuDesktopRemoteShell这个名称部署于Spring。
∙该收集器不会硬编码一组命令及其相关解析例程,而是使用mands.CommandSet的一个实例,它将以UbuntuDesktopCommandSet这个名称部署于Spring中。
命令集从一个XML文档载入,该文档表述了:
o将要用来执行shell的目标平台
o将要执行的命令
o将如何解析返回数据并将其映射到APM跟踪命名空间
稍候我将提供有关这些定义的更多细节。
图2大致解释了收集器、shell和命令集三者之间的关系:
图2.收集器、shell和命令集
下面我将专门介绍一些关于专用于生成性能数据的命令以及它们的配置方法的简短示例。
一个经典的例子就是sar命令。
Linux手册(参见参考资料)对sar的定义是收集、报告或者保存系统活动信息。
该命令非常灵活,它有超过20个参数,这些参数可以结合起来使用。
一个简单的选择就是调用sar-u13,它报告了在三个时间间隔内(一个时间间隔为一秒)度量的CPU使用。
清单2展示了它的输出:
清单2.sar命令的输出
whitehen@whitehen-desktop:
~$sar-u13
Linux2.6.22-14-generic(whitehen-desktop06/02/2008
06:
53:
24PMCPU%user%nice%system%iowait%steal%idle
06:
53:
25PMall0.000.000.000.000.00100.00
06:
53:
26PMall0.0035.710.000.000.0064.29
06:
53:
27PMall0.0020.790.990.000.0078.22
Average:
all0.0018.730.330.000.0080.94
该输出可以划分成开头、标题、三个时间间隔的数据读数和一个读数汇总平均值。
这里的目标是要执行该shell命令、捕获输出,然后解析输出并跟踪到APM系统。
输出数据的格式是够简单的,但却可能根据具体的版本而不同(轻微或显著的不同),而且其他sar选项也会返回完全不同的数据(更不用说其他的命令了,它们当然会返回不同的数据格式)。
例如,清单3展示了一个显示活动的socket行为的sar执行:
清单3.显示socket行为的sar
whitehen@whitehen-desktop:
~$sar-nSOCK1
Linux2.6.22-14-generic(whitehen-desktop06/02/2008
06:
55:
10PMtotscktcpsckudpsckrawsckip-frag
06:
55:
11PM4537900
Average:
4537900
因此,现在所需要的是一个解决方案:
怎样在不重新编码收集器的情况下快速配置不同的数据。
还可以将诸如totsck这样的含糊词语翻译成像TotalUsedSockets这样的更易读的短语,以免收集到的记录会干扰APM系统。
在某些情况下,您可以选择以XML格式获取这个数据。
例如,SysStat包(参见参考资料)中的sadf命令会以XML格式生成很多被经常收集的Linux监控数据。
XML格式增加了数据的可预测性和结构,并真正排除了分析数据、将数据映射到跟踪名称空间和解码模糊词语的需要。
然而,这些工具对于您想监控的可以访问shell的系统可能是不可用的,因此需要一种灵活的文本解析和映射解决方案。
承接上面两个关于sar的应用的例子,接下来我将呈现一个设置Springbean定义以监控这些数据的例子。
所有引用的例子都包含在本文的示例代码中(参见下载)。
首先,SpringCollector实现的主要入口点为org.runtimemonitoring.spring.collectors.SpringCollector。
它采用了一个参数:
Springbean配置文件所在的目录的名称。
SpringCollector载入了任何带有.xml扩展名的文件,并将他们当作bean描述符。
该目录为位于项目根目录中的./spring-collectors目录(稍后我将在本文中概述此目录中的所有文件。
有多个文件可以选择,而且可以将所有的定义捆绑成一个,但要用虚构的函数单独隔开,以保持一定的顺序)。
这个例子中的三个bean定义代表shell收集器、shell和命令集。
清单4展示了它们的描述符:
清单4.shell收集器、shell与命令集的Bean描述符
1.
2.
3. class="org.runtimemonitoring.spring.collectors.shell.ShellCollector"
4. init-method="springStart">
5.
6.
7.
8.
9.
10.
11.
12.
13.
14. class="org.runtimemonitoring.spring.collectors.shell.ssh.JSchRemoteShell"
15. init-method="init"
16. destroy-method="close">
17.
18.
19.
20.
21. value="C:
/Documents and Settings/whitehen/.ssh/known_hosts"/>
22.
23. value="C:
/keys/whitehen/ubuntu-desktop/whitehen_dsa"/>
24.
25.
26.
27.
28.
29. class="mands.CommandSet">
30.
31. value="file:
///C:
/projects//RuntimeMonitoring/commands/xml/UbuntuDesktop.xml"/>
32.
33.
清单4中的CommandSet只有一个id(UbuntuDesktopCommandSet)和另一个XML文件的URL。
这是因为命令集太大,我不想因为它们而使Spring文件显得很混乱。
稍后我将描述CommandSet。
清单3中的第一个bean为UbuntuDesktopRemoteShellCollector。
它的beanid值可以是任意的描述性的值,但是当从另一个bean引用该bean时需要保持一致。
这个例子中的类为org.runtimemonitoring.spring.collectors.shell.ShellCollector,它是一个通过类似于Shell的接口来收集数据的通用类。
其他重要属性有:
∙shell:
收集器用来从shell命令调用和检索数据的shell类的实例。
Spring用UbuntuDesktopCommandSet的beanid来注入该Shell的实例。
∙commandSet:
代表一组命令和相关解析、跟踪名称空间映射指令的CommandSet实例。
Spring用UbuntuDesktopRemoteShell的beanid注入该命令集的示例。
∙scheduler:
一个调度线程池的引用,该线程池管理数据收集的调度,将这项工作具体分配给一个线程来完成。
∙tracingNameSpace:
跟踪名称空间的前缀,它控制着这些指标将被跟踪到APM树中的哪个位置。
∙frequency:
数据收集频率,以毫秒为单位。
清单4中的第二个bean为shell,它是一个名为org.runtimemonitoring.spring.collectors.shell.ssh.JSchRemoteShell的SSHshell的实现。
该类使用从JC(参见参考资料)下载的JSch来实现。
它的其他重要属性有:
∙userName:
用户用来连接到Linux服务器的名称
∙hostName:
连接到的Linux服务器的名称(或IP地址)。
∙port:
Linux服务器端口,sshd在这个端口上监听。
∙knownHostFile:
一个包含主机名称和SSH服务器的SSH证书的文件,该SSH服务器对于运行SSH客户机的本地主机是“已知的”(有趣的是,SSH中的这个安全机制恰好颠倒了传统的安全结构,使用这种机制,除非主机是“已知的”并可以给出匹配的证书,否则客户机不会信任主机,并拒绝连接)。
∙privateKey:
用来验证SSH服务器的SSH私钥文件。
∙passPhrase:
用来解锁私钥的密码短语。
它的外表与密码类似,只是它没有被传送到服务器,而且它只用于本地解密私钥。
清单5展示了CommandSet的内部细节:
清单5.CommandSet内部细节
1.
2.
3.
4. sar -u 1
5. \n\n
6.
7.
8.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java 运行时监控第 部分 监控应用程序生态系统的性 运行 监控 应用程序 生态系统