• 蛙蛙推荐:自己写个分布式监控软件玩


    摘要

    如果你有多台windows服务器需要监控,又不想买很贵的MOM,开源的监控软件部署配置又麻烦,咋办?.net公开了好多监控和管理方面的API,jquery有一些跨浏览器的图表插件,有了这些就可以自己做一个符合自己需求的监控软件。

    思路:
    1、要监控一个服务器的运行状况,可能有很多指标,比如某端口是否监听,某进程是否还存在,是否产生了某个EventID的EventLog,某些性能计数器是否达到阈值,其中性能计数器的监控是最重要的,因为服务器上运行的服务都会有一组自己独有的计数器,用于监控该服务的健康状况,比如SQLSERVER,EXCHANGE等。
    2、要监控性能计数器,第一是先建立基准线,根据平时观察到的正常情况下各个关键性能计数器的值的得范围是多少,然后指定阈值,超过这个阈值就给予报警,这阈值通常和服务的负载情况有很大关系,所以阈值可能会随着业务的发展而不断调整。
    3、在.NET里可以使用PerformanceCounter类来获取某个具体性能计数器的采样值,用的最多的可能就是其NextValue()方法,该方法第一次执行的值为0,只有第二次及之后的值才会是实际值,关于各种类型计数器的语义,请参考后面的参考链接。
    4、默认情况下ASP.NET的运行账户没有权限读取性能计数器,更别提远程机器的性能计数器了,不过我们应该可以使用ASP.NET模拟或者指定该程序的运行标识来解决。多台服务器的管理一般都会使用域,申请一个能获取所有服务器性能计数器权限的账户来运行该ASP.NET应用就可以了。
    5、为了方便监控,我们使用WEB形式来监控,而web形式下图表的生成和刷新是个问题,如果完全由服务器来生成图表的图片,性能可能会很差一些,幸亏有一些免费开源的纯客户端图表组件可以用,最后发现jquery flot能满足需求,图表类型丰富,浏览器兼容性好,IE6/7/8,FF都支持。
    6、我们用一个ashx页面来专门产生计数器的数据,然后客户端用jquery每隔一秒钟访问该页面,获取性能计数器数据,并提供给flot组件,在客户端实施更新图表。

    代码:
    1、生成性能计数器数据
    写一个专门的HttpHandler来提供性能计数器数据,返回的格式是JSON格式,因为flot自身的原因,处理时间的X轴有问题,所以得到时间后要加上8小时的毫秒数,然后客户端才能解析成正确的北京时间,另外就是时间格式上注意一下,日期的分隔符用/不能用-,否则JS不认。

    public void ProcessRequest(HttpContext context) {
        context.Response.ContentType 
    = "text/plain";
        context.Response.Buffer 
    = true;
        context.Response.ExpiresAbsolute 
    = DateTime.Now.AddSeconds(-1);
        context.Response.Expires 
    = 0;
        context.Response.CacheControl 
    = "no-cache";

        StringBuilder output 
    = new StringBuilder();
        DateTimeFormatInfo formatInfo 
    = new DateTimeFormatInfo();
        formatInfo.DateSeparator 
    = "/";
        output.Append(
    "[");

        PerformanceCounter counter 
    = PerfCounterFactory.Instance.GetCounter
            (
    "Processor|% Processor Time|_Total|.");
        output.AppendFormat(
    "[new Date(\"{0}\").getTime()+28800000, {1}]",
                                      DateTime.Now.ToString(
    "yyyy/MM/dd hh:mm:ss",formatInfo),
                                      counter.NextValue().ToString(
    "0.0"));

        output.Append(
    ",");
        counter 
    = PerfCounterFactory.Instance.GetCounter(
            
    "Memory|Available Bytes||.");
        output.AppendFormat(
    "[new Date(\"{0}\").getTime()+28800000, {1}]",
                                      DateTime.Now.ToString(
    "yyyy/MM/dd hh:mm:ss", formatInfo),
                                      counter.NextValue().ToString(
    "0.0"));
        output.Append(
    "]");

        context.Response.Write(output);
    }

    浏览该页,显示应该类似如下
    [[new Date("2009/06/20 02:24:43").getTime()+28800000, 70.0],[new Date("2009/06/20 02:24:43").getTime()+28800000, 615792600.0]]

    2、图表的呈现
    1)、图表的呈现就是纯客户端逻辑了,首先在head里引用juqery和flot的js,然后在BODY里声明用于放图表和图例的div,分别是placeholder和legend,
    2)、声明两个全局数组_d1和_d2,用于保存两个计数器的数据,_chartOptions用来配置图表呈现的选项,因为我们同时显示CPU和内存情况,所以用双Y轴模式,另外把X轴设置为时间模式,还有就是默认情况下图例和图表在一个区域,但有时候图例会遮盖住曲线,所以故意使用container: $("#legend")把图例放在单独的布局块儿里,右Y轴显示可用内存数,我们用suffixFormatter函数来动态的更新右Y轴的单位。
    3)、在document.read事件里每隔1秒钟去访问perfcounter.ashx页面,为了防止浏览器缓存数据,在地址后面挂了个随机数。获取到计数器数据后,把相应的数据放入_d1和_d2中,如果采集的数据点超过100,就把最前面的数据点挤出去,这样防止客户端的内存越来越大,而且我们只看最近一段时间的计数器曲线图。
    4)、获取到数据后,调用$.plot方法呈现图表,并把_d1和_d2传进去,同时设置_d2使用右Y轴,呈现完后再设置1秒后执行第3步。

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        
    <title>监控</title>
        
    <link href="layout.css" rel="stylesheet" type="text/css"></link>
        
    <!--[if IE]><script language="javascript" type="text/javascript" src="scripts/excanvas.pack.js"></script><![endif]-->
        
    <script language="javascript" type="text/javascript" src="scripts/jquery.js"></script>
        
    <script language="javascript" type="text/javascript" src="scripts/jquery.flot.js"></script>
    </head>
    <body>
        
    <form id="form1" runat="server">
        
    <h1>
            本机CPU使用率和可用内存实施监控
    </h1>
        
    <div>
            
    <div id="placeholder" style=" 600px; height: 300px;">
            
    </div>
            
    <div id="legend" style="top: 400px;  600px; height: 50px;">
            
    </div>
            
    <div id="trace">
            
    </div>
        
    </div>

        
    <script id="source" language="javascript" type="text/javascript">
            
    var _d1 = [];
            
    var _d2 = [];
            
    var _chartOptions = {
                xaxis: { mode: 
    "time" },
                series: {
                    lines: { show: 
    true },
                    points: { show: 
    true }
                },
                legend: {
                    show: 
    true,
                    container: $(
    "#legend")
                },
                yaxis: { min: 
    0 },
                y2axis: { tickFormatter: suffixFormatter }
            };
            
            $(
    function() {
                window.setTimeout(
    function() {
                    GetData()
                }, 
    1000);
            });

            
    function GetData() {
                $.getJSON(
    "perfcounter.ashx?" + Math.random(), showPercounter);
            }
            
    function showPercounter(data) {
                
    //$("#trace").html($("#trace").html()+"<br>"+data);
                _d1.push(data[0]);
                
    if (_d1.length >= 100) _d1.shift();
                _d2.push(data[
    1]);
                
    if (_d2.length >= 100) _d2.shift();
                
                $.plot($(
    "#placeholder"),
                    [{ label: 
    "Processor\\% Process Time", data: _d1 },
                     { label: 
    "Memory\\Availibel Bytes", data: _d2, yaxis: 2}],
                    _chartOptions);
                window.setTimeout(
    function() {
                    GetData()
                }, 
    1000);
            }
            
    function suffixFormatter(val, axis) {
                
    if (val > 1000000)
                    
    return (val / 1000000).toFixed(axis.tickDecimals) + " MB";
                
    else if (val > 1000)
                    
    return (val / 1000).toFixed(axis.tickDecimals) + " kB";
                
    else
                    
    return val.toFixed(axis.tickDecimals) + " B";
            }
        
    </script>

        
    </form>
    </body>
    </html>

    3、看看成果,如下图 

    图表的效果还是不错的,而且是实施的,用椭圆扩住的地方发现CPU上升,可用内存下降,是我用风雷影音打开了一个720P的电影。

    4、后记
    本文只是一个演示性的东西,知道原理后可以做一个功能强大,灵活可配置的web监控软件,比如采样频率的配置,是否保存到数据库,同时显示多台机器的CPU使用情况,设置某个计数器达到阈值后播放一段报警声音等等。

    5、参考链接
    蛙蛙推荐:创建自己的性能计数器及压力测试入门
    http://www.cnblogs.com/onlytiancai/archive/2007/09/22/902310.html
    蛙蛙推荐:编写一个服务监控及管理的软件
    http://www.cnblogs.com/onlytiancai/archive/2008/02/17/1071409.html       
    .NET Framework 中的性能计数器
    http://msdn.microsoft.com/zh-cn/library/w8f5kw2e(VS.80).aspx
    PerfMon – Your debugging buddy
    http://dotnetdebug.net/2005/06/30/perfmon-your-debugging-buddy/
    使用系统监视组件
    http://msdn.microsoft.com/zh-cn/library/aaaxk5bx(VS.80).aspx
    jquery flot
    http://code.google.com/p/flot/

    代码下载地址如下
    https://files.cnblogs.com/onlytiancai/WawaMointer.rar

  • 相关阅读:
    2017icpc青岛
    训练赛
    CF1598F
    CF1581
    CF1594
    CF1581D
    codeforces round 746 div2 C-E
    How I Think About Learning
    Linux Sysadmin Basics 4.1 -- Filtering Output and Finding Things (&&, cut, sort, uniq, wc, grep)
    Linux Sysadmin Basics 04 -- Shell Features -- Pipes and Redirection
  • 原文地址:https://www.cnblogs.com/onlytiancai/p/wawa_mointer.html
Copyright © 2020-2023  润新知