使用PowerShell收集多台服务器的性能计数器
写在前面
当管理多台Windows Server服务器时(无论是DB、AD、WEB以及其他的应用服务器),当出现性能或其他问题后,参阅性能计数器都是一个非常好的维度从而推测出问题可能出现的原因,再不济也能缩小需要考虑的问题范围,因此定期收集每一台服务器的计数器就会使得问题有据可循。并且收集到的数据也可以作为BaseLine,即使没有出现问题也可以预先判断一些问题。
之前看到网上的大多数收集性能计数器的文章都比较局限,一般是只收集单台服务器,因此我分享一个多服务器的写法。
至于为什么使用PowerShell,因为在微软系产品来说像Python等脚本语言虽然有丰富的开源代码没有太好的对应接口,而PowerShell每一个微软自己的产品都提供了大量的Cmdlet,调用起来甚是方便:-)
核心Cmdlet
获取性能计数器的核心cmdlet就是Get-Counter了,该Get-Counter主要使用两个参数,分别为要获取的计算机名称-ComputerName与性能计数器列表-Counter,这里要注意的是,获取性能计数器需要在被获取服务器有对应权限(Performance Monitor Users组),我这里的例子是使用域管理员帐号收集域内服务器,因此不考虑权限问题。

图1.获取到的远程服务器性能计数器
然后将获取到的结果保存到变量中,如图2所示。

图2.将计数器结果保存到变量中
收集多台服务器的多个计数器
将所需收集的服务器以及所需收集的计数器保存到记事本内,方便随时添加或减少服务器或者计数器,记事本写法如下:

图3.计数器与服务器配置
在PowerShell中使用Get-Content读取配置文件内容,如下:
$currentPath=Split-Path ((Get-Variable MyInvocation -Scope 0).Value).MyCommand.Path
#读取需要收集的性能计数器列表
$ServerNeedScan=get-content $currentPath\ServerNeedScan.txt
$ServerNeedScanArray=$ServerNeedScan.Split(",")
#读取需要收集的性能计数器
$PerfCounter=get-content $currentPath\PerfmonCounter.txt
$PerfCounterArray=$PerfCounter.Split(",")
代码1.读取服务器列表和计数器列表
现在由于收集的计数器中部分计数器是关于SQL Server的,而部分服务器可能带有实例名称,而对于带有SQL Server实例名称的计数器需要把实例和及其名分开,然后把计数器名称中实例名部分进行替换,代码如下:
foreach ($fcomputer in $ServerNeedScanArray)
{
if($fcomputer.Trim() -eq "")
{
continue
}
#检查是否为默认实例
$computer=""
if($fcomputer -like "*\*")
{
$instanceName=$fcomputer.Substring($fcomputer.IndexOf("\")+1,$fcomputer.Length-$fcomputer.IndexOf("\")-1)
$computer=$fcomputer.Substring(0,$fcomputer.IndexOf('\'))
}
else
{
$computer=$fcomputer
$instanceName=""
}
#遍历所有计数器
$fullCounter=@()
foreach($counter in $PerfCounterArray)
{
$c=""
$c+="\"
$c+=$counter
$fullCounter+=$c
}
$NoDeaultInstanceName="MSSQL`$"
$NoDeaultInstanceName+=$instanceName
#如果是默认实例
if($instanceName -eq "")
{
$fullCounter | % {
if($_ -like "*network*")
{
$finalCounter+= $_.ToLower()
}
else
{
$finalCounter+= $_.ToLower().Replace("*","_total")
}
}
}
#如果是非默认实例
else
{
$a=$fullCounter | % {
if($_ -like "*network*")
{
$finalCounter+= $_.ToLower().Replace("sqlserver", $NoDeaultInstanceName)
}
else
{
$finalCounter+= $_.ToLower().Replace("*","_total").Replace("sqlserver", $NoDeaultInstanceName)
}
}
}
代码2.替换SQL Server计数器中的非默认实例
将结果插入一台SQL Server
上述情况就已经准备好了计数器和服务器名称,现在就可以将这些数据插入到一台集中的SQL Server服务器,代码如下:
$a=(Get-Counter -ComputerName $computer -Counter $finalCounter).CounterSamples |Select-Object Path,CookedValue
$InsertSQL=""
$curentTime=Get-Date
foreach($PerformanceCounter in $a)
{
$realvalue=$PerformanceCounter.CookedValue
$InsertSQL+="INSERT INTO PerfCounter(instancename,event_timestamp,Counter,CounterValue)
VALUES(''"+$fcomputer+"'',''"+$curentTime+"'',''"+$PerformanceCounter.Path+"'',''"+$realvalue.ToString()+"'');"
}
$connectionString3="data source=服务器IP;database=test;uid=perf_writer;pwd=123123;"
$conn2=new-object system.Data.SqlClient.SqlConnection($connectionString3)
$conn2.open()
$cmd2=$conn2.CreateCommand()
$cmd2.CommandText=$InsertSQL
$cmd2.ExecuteNonQuery()
$conn2.Close()
代码3.读取计数器后插入SQL Server
现在,读取一台服务器并将计数器记录到数据库中的代码就写好了,并且已经可以灵活配置需要读取的计数器和机器名。
多线程读取
如果需要记录计数器的服务器比较多时,那么循环遍历每一台服务器就会花费比较长的时间,因此需要多线程来加快这一个速度,在PowerShell中,启用多线程的cmdlet是start-job,我们首先需要将代码2和代码3的脚本封装到一个script block中,并设置可传入的参数,如代码4。
$sb = [scriptblock]::Create('
param($instanceName,$NoDeaultInstanceName,$fullCounter,$fcomputer,$computer)
#这里写其他代码
')
#开始异步线程,并传入参数
start-job -scriptblock $sb -Argument $instanceName,$NoDeaultInstanceName,$fullCounter,$fcomputer,$computer
代码4.利用异步线程读取计数器数据并插入SQL Server
经过测试,PowerShell对同时可以并发的线程做了限制,这个限制很奇怪,我在每台服务器上测试的结果并不相同,因此如果同时全部并发执行这些线程,某些线程会因为限制而不起作用,因此如果需要记录性能计数器的服务器比较多的话,会丢失一部分服务器信息,我的解决办法是限制同时并发的进程数量,如果进程数量超过规定数值,则等待1秒再次检测,如果检测通过再启动新进程,代码如代码5所示。
While (@(Get-Job | Where { $_.State -eq "Running" }).Count -gt 5) {
Write-host "Waiting for background jobs..."
Start-Sleep -Seconds 1
}
代码5.检测处于“运行中”进程的数量是否大于5
定期执行脚本
现在,上面脚本就可以收集多台服务器的性能计数器,并将结果保存到SQL Server了,现在只需要定期(比如2分钟一次)执行该脚本即可。使用Windows计划任务是定期执行PowerShell脚本推荐的方式,如图4所示。

图4.使用计划任务2分钟收集一次性能计数器信息
在图4中,我们注意到使用了-NonInteractive参数,该参数用于在执行时,不弹出PowerShell窗口。
结果
现在,我们可以看到收集后的性能计数器信息,如图5所示。

图5.收集到的性能计数器信息
有了上述性能计数器信息,我们可以使用一些可视化工具分析这些信息,比如我将数据导入到ElasticSearch中,出几张简单的报表,如图6所示。

图6.使用这些性能计数器出简单的报表
这些报表可以帮助我们直观的看出一些问题,比如图6中的forward record可以看到,某些实例大量缺少聚集索引,或者下面的Top Lock Wait可以看到某些实例定期会产生大量的锁阻塞,从而我们可以更容易提前发现问题,进行解决。
小结
定期收集一些服务器的信息可以帮助在运维工作中掌握主动,在业务中现在流行所谓的“大数据促进决策”,其实在IT运维本身中,收集大量的数据同样重要,通过数据我们甚至可以在问题出现之前发现问题。
在WIndows下PowerShell无疑是最适合做这一工作的语言。
使用PowerShell收集多台服务器的性能计数器的更多相关文章
- logstash+redis收集负载均衡模式下多台服务器的多个web日志
一.logstash的简介 一般我们看日志来解决问题的时候要么 tail+grep 要么 把日志下载下来再搜索,可以应付不多的主机和应用不多的部署场景.但对于多机多应用部署就不合适了.这里的多机多应用 ...
- SQL Server自动化运维系列——关于数据收集(多服务器数据收集和性能监控)
需求描述 在生产环境中,很多情况下需要采集数据,用以定位问题或者形成基线. 关于SQL Server中的数据采集有着很多种的解决思路,可以采用Trace.Profile.SQLdiag.扩展事件等诸多 ...
- 删除HT和CAS角色与扩展在另一台服务器
背景:原先使用三合一方式部署的架构,如今不再满足企业需求,因此需要将原来的一台服务器多角色的拆分开,即由原来CAS.HT.MBX角色集一台服务器的分成两台服务器来部署,此架构为MBX角色单独部署在 ...
- Dynamics 365 for CRM:CRM与ADFS安装到同一台服务器,需修改ADFS服务端口号
CRM与ADFS安装到同一台服务器时,出现PluginRegistrationTool 及 CRM Outlook Client连接不上,需要修改ADFS的服务端口号,由默认的808修改为809: P ...
- zabbix 创建主机、主机群组、监控第一台服务器
前面介绍了zabbix服务器和zabbix agent的安装配置,今天使用zabbix监控第一台服务器. 1. 安装zabbix agent 在被监控的服务器上安装zabbix agent . 参考& ...
- SRV记录用来标识某台服务器使用了某个服务,常见于微软系统的目录管理——深入的话需要去折腾Azure Active Directory
SRV记录 SRV记录 什么情况下会用到SRV记录? [SRV记录用来标识某台服务器使用了某个服务,常见于微软系统的目录管理] SRV记录的添加方式 A.主机记录处格式为:服务的名字.协议的类型 例如 ...
- 搭建jumperserver堡垒机管理万台服务器-1
搭建jumperserver堡垒机管理万台服务器-1 1 Jumpserver堡垒机概述-部署Jumpserver运行环境 2 安装Coco组件 3 安装Web-Terminal前端-Luna组 ...
- Dynamics CRM与ADFS安装到同一台服务器后ADFS服务与Dynamics CRM沙盒服务冲突提示808端口占用问题
当我们安装Dynamics CRM的产品时如果是单台服务器部署而且部署了IFD的情况会遇到一个问题就是ADFS服务的监听端口和Dynamics CRM沙盒服务的端口冲突了. 这样会导致两个服务中的一个 ...
- ElasticSearch 5学习(3)——单台服务器部署多个节点
一般情况下单台服务器只会部署一个ElasticSearch node,但是在学习过程中,很多情况下会需要实现ElasticSearch的分布式效果,所以需要启动多个节点,但是学习开发环境(不想开多个虚 ...
随机推荐
- .Net多线程编程—预备知识
1 基本概念 共享内存的多核架构:一个单独的封装包内封装了多个互相连接的未处理器,且所有内核都可以访问主内存.共享内存的多核系统的一些微架构,例如内核暂停功能,超频. 内核暂停功能:当使用内核不多的时 ...
- 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法
若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...
- 快递Api接口 & 微信公众号开发流程
之前的文章,已经分析过快递Api接口可能被使用的需求及场景:今天呢,简单给大家介绍一下微信公众号中怎么来使用快递Api接口,来完成我们的需求和业务场景. 开发语言:Nodejs,其中用到了Neo4j图 ...
- BPM配置故事之案例10-获取外部数据
老李:Hi,小明,我又来了 小明:--这次又怎么了. 老李:之前的物资管理方式太混乱了,这段时间我整理了采购物资清单,现在都录入到我们的ERP中了,以后申请物资改成从ERP数据选择吧.物资明细表我也做 ...
- ios 获取或修改网页上的内容
UIWebView是iOS最常用的SDK之一,它有一个stringByEvaluatingJavaScriptFromString方法可以将javascript嵌 入页面中,通过这个方法我们可 ...
- iOS从零开始学习直播之2.采集
直播的采集由采集的设备(摄像头.话筒)不同分为视频采集和音频采集,本篇文章会分别介绍. 1.采集步骤 1.创建捕捉会话(AVCaptureSession),iOS调用相机和话筒之前都需要创建捕 ...
- windows10安装mysql5.7.17是这样安装的吗?
操作 全允许
- Yeoman 学习笔记
yoeman 简介:http://www.infoq.com/cn/news/2012/09/yeoman yeoman 官网: http://yeoman.io/ yeoman 是快速创建骨架应用程 ...
- mono-3.4.0 源码安装时出现的问题 [do-install] Error 2 [install-pcl-targets] Error 1 解决方法
Mono 3.4修复了很多bug,继续加强稳定性和性能(其实Mono 3.2.8 已经很稳定,性能也很好了),但是从http://download.mono-project.com/sources/m ...
- HTML5- Canvas入门(五)
今天要介绍的是canvas对图形对象的操作,包括图像.视频绘制,和操作像素对象的方法. 图片/视频的绘制 在canvas中,我们可以通过 drawImage() 的方法来绘制图片或视频文件,其语法为: ...