写在前面

    当管理多台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收集多台服务器的性能计数器的更多相关文章

  1. logstash+redis收集负载均衡模式下多台服务器的多个web日志

    一.logstash的简介 一般我们看日志来解决问题的时候要么 tail+grep 要么 把日志下载下来再搜索,可以应付不多的主机和应用不多的部署场景.但对于多机多应用部署就不合适了.这里的多机多应用 ...

  2. SQL Server自动化运维系列——关于数据收集(多服务器数据收集和性能监控)

    需求描述 在生产环境中,很多情况下需要采集数据,用以定位问题或者形成基线. 关于SQL Server中的数据采集有着很多种的解决思路,可以采用Trace.Profile.SQLdiag.扩展事件等诸多 ...

  3. 删除HT和CAS角色与扩展在另一台服务器

      背景:原先使用三合一方式部署的架构,如今不再满足企业需求,因此需要将原来的一台服务器多角色的拆分开,即由原来CAS.HT.MBX角色集一台服务器的分成两台服务器来部署,此架构为MBX角色单独部署在 ...

  4. Dynamics 365 for CRM:CRM与ADFS安装到同一台服务器,需修改ADFS服务端口号

    CRM与ADFS安装到同一台服务器时,出现PluginRegistrationTool 及 CRM Outlook Client连接不上,需要修改ADFS的服务端口号,由默认的808修改为809: P ...

  5. zabbix 创建主机、主机群组、监控第一台服务器

    前面介绍了zabbix服务器和zabbix agent的安装配置,今天使用zabbix监控第一台服务器. 1. 安装zabbix agent 在被监控的服务器上安装zabbix agent . 参考& ...

  6. SRV记录用来标识某台服务器使用了某个服务,常见于微软系统的目录管理——深入的话需要去折腾Azure Active Directory

    SRV记录 SRV记录 什么情况下会用到SRV记录? [SRV记录用来标识某台服务器使用了某个服务,常见于微软系统的目录管理] SRV记录的添加方式 A.主机记录处格式为:服务的名字.协议的类型 例如 ...

  7. 搭建jumperserver堡垒机管理万台服务器-1

    搭建jumperserver堡垒机管理万台服务器-1 1  Jumpserver堡垒机概述-部署Jumpserver运行环境 2  安装Coco组件 3  安装Web-Terminal前端-Luna组 ...

  8. Dynamics CRM与ADFS安装到同一台服务器后ADFS服务与Dynamics CRM沙盒服务冲突提示808端口占用问题

    当我们安装Dynamics CRM的产品时如果是单台服务器部署而且部署了IFD的情况会遇到一个问题就是ADFS服务的监听端口和Dynamics CRM沙盒服务的端口冲突了. 这样会导致两个服务中的一个 ...

  9. ElasticSearch 5学习(3)——单台服务器部署多个节点

    一般情况下单台服务器只会部署一个ElasticSearch node,但是在学习过程中,很多情况下会需要实现ElasticSearch的分布式效果,所以需要启动多个节点,但是学习开发环境(不想开多个虚 ...

随机推荐

  1. 【小程序分享篇 二 】web在线踢人小程序,维持用户只能在一个台电脑持登录状态

    最近离职了, 突然记起来还一个小功能没做, 想想也挺简单,留下代码和思路给同事做个参考. 换工作心里挺忐忑, 对未来也充满了憧憬与担忧.(虽然已是老人, 换了N次工作了,但每次心里都和忐忑). 写写代 ...

  2. 编写高质量代码:改善Java程序的151个建议(第5章:数组和集合___建议75~78)

    建议75:集合中的元素必须做到compareTo和equals同步 实现了Comparable接口的元素就可以排序,compareTo方法是Comparable接口要求必须实现的,它与equals方法 ...

  3. BZOJ 1911: [Apio2010]特别行动队 [斜率优化DP]

    1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 4142  Solved: 1964[Submit][Statu ...

  4. 【社工】NodeJS 应用仓库钓鱼

    前言 城堡总是从内部攻破的.再强大的系统,也得通过人来控制.如果将入侵直接从人这个环节发起,那么再坚固的防线,也都成为摆设. 下面分享一个例子,利用应用仓库,渗透到开发人员的系统中. 应用仓库 应用仓 ...

  5. JAVA回调机制(CallBack)详解

    序言 最近学习java,接触到了回调机制(CallBack).初识时感觉比较混乱,而且在网上搜索到的相关的讲解,要么一言带过,要么说的比较单纯的像是给CallBack做了一个定义.当然了,我在理解了回 ...

  6. 关于微软HttpClient使用,避免踩坑

    最近公司对于WebApi的场景使用也越来越加大了,随之而来就是Api的客户端工具我们使用哪个?我们最常用的估计就是HttpClient,在微软类库中命名空间地址:System.Net.Http,是一个 ...

  7. # PHP - 使用PHPMailer发邮件

    PHPMailer支持多种邮件发送方式,使用起来非常简单 1.下载PHPMailer https://github.com/PHPMailer/PHPMailer,下载完成加压后, 把下边的两个文件复 ...

  8. 在Windows上编译和调试CoreCLR

    生成CoreCLR - Windows篇 本文的唯一目的就是让你运行Hello World 运行环境 Window 7+ Visual studio 2015 确保C++ 工具已经被安装,默认是不安装 ...

  9. gulp初学

    原文地址:gulp初学 至于gulp与grunt的区别,用过的人都略知一二,总的来说就是2点: 1.gulp的gulpfile.js  配置简单而且更容易阅读和维护.之所以如此,是因为它们的工作方式不 ...

  10. QQ空间动态爬虫

    作者:虚静 链接:https://zhuanlan.zhihu.com/p/24656161 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 先说明几件事: 题目的意 ...