虽然有很多开源工具通过插件或其它方式可以监测这些开源组件提供的内在性能(所谓内在性能就是这些开源组件提供的类STAT命令获取到的数据),但是不管是部署还是扩展都很麻烦,其实花1-2天时间完全可以实现一个这样的工具,并且扩展起来也很方便。
比如mongodb的:
又比如redis的:
这个工具实现的功能如下:
1)只需要简单配置(在DEMO代码里我硬编码了,您完全可以改为通过配置)就可以实现监控redis、mongodb、kt和memcached,之所以只有这些因为我们用到的只有这些,其实扩展一下也很方便,特别是有.NET客户端的组件。
2)监控粒度可以选择,不同的监控粒度在一页上显示的时间段也不一样,大致确保一页100个点左右。
3)为了简单,分页只是做了下拉,您完全可以修改为拖动或分页控件。
这个工具实现的原理如下:
1)利用mongodb保存大量数据,为了性能使用了mongodb的Capped集合,而且这样也无需考虑历史数据的移除。
2)10秒的监控粒度是原始收集数据的粒度,通过收集器定时收集数据,直接写入Mongodb。
3)其它监控粒度是基于原始数据的聚合,聚合器定时聚合数据,也是使用Capped集合,不过集合大小会小一点。
4)值的类型如下:
public enum ItemValueType { TextValue, StateValue, TotalValue, ExpressionValue, }
对于StateValue也就是状态值直接存入数据库,对于TotalValue也就是总数值,会在内存中保存上一个值然后下一个值收集到之后会进行相减获取到差值,对于TextValue始终保存最新的值,对于ExpressionValue暂时没有做处理,您可以自己实现,对于Mongodb来说我们选择监测这些数据:
private static Dictionary<string, ComponentItem> items = new Dictionary<string, ComponentItem> { { "version", new ComponentItem("其它", "版本号", ItemValueType.TextValue) }, { "mem.resident", new ComponentItem("内存", "使用的物理内存大小", ItemValueType.StateValue) }, { "mem.virtual", new ComponentItem("内存", "使用的虚拟内存大小", ItemValueType.StateValue) }, { "mem.mapped", new ComponentItem("内存", "映射的内存大小", ItemValueType.StateValue) }, { "mem.mappedWithJournal", new ComponentItem("内存", "具有日志的映射的内存大小", ItemValueType.StateValue) }, { "extra_info.page_faults", new ComponentItem("内存", "加载磁盘内容时发生页错误的次数", ItemValueType.TotalValue) }, { "connections.current", new ComponentItem("连接", "当前连接数", ItemValueType.StateValue) }, { "connections.available", new ComponentItem("连接", "可用连接数", ItemValueType.StateValue) }, { "network.bytesIn", new ComponentItem("网络", "网络读取字节数", ItemValueType.TotalValue) }, { "network.bytesOut", new ComponentItem("网络", "网络发送字节数", ItemValueType.TotalValue) }, { "network.numRequests", new ComponentItem("网络", "网络请求数", ItemValueType.TotalValue) }, { "opcounters.insert", new ComponentItem("操作数", "insert数", ItemValueType.TotalValue) }, { "opcounters.query", new ComponentItem("操作数", "query数", ItemValueType.TotalValue) }, { "opcounters.update", new ComponentItem("操作数", "update数", ItemValueType.TotalValue) }, { "opcounters.delete", new ComponentItem("操作数", "delete数", ItemValueType.TotalValue) }, { "opcounters.getmore", new ComponentItem("操作数", "游标getmore数", ItemValueType.TotalValue) }, { "opcounters.command", new ComponentItem("操作数", "其它操作数", ItemValueType.TotalValue) }, { "indexCounters.btree.accesses", new ComponentItem("索引", "访问索引次数", ItemValueType.TotalValue) }, { "indexCounters.btree.hits", new ComponentItem("索引", "内存命中索引次数", ItemValueType.TotalValue) }, { "indexCounters.btree.misses", new ComponentItem("索引", "内存不命中索引次数", ItemValueType.TotalValue) }, { "indexCounters.btree.resets", new ComponentItem("索引", "索引计数器重置次数", ItemValueType.TotalValue) }, { "indexCounters.btree.hits * 100 / indexCounters.btree.accesses", new ComponentItem("索引", "hitsratio ", ItemValueType.ExpressionValue) }, };
5)客户端很简单,使用了highchart+ajax,直接和wcf的服务端交互获取jsonp数据源。
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="ServiceBehaviour" > <serviceDebug includeExceptionDetailInFaults="true"/> <serviceMetadata /> </behavior> </serviceBehaviors> <endpointBehaviors> <behavior name="HttpBehaviour"> <webHttp defaultBodyStyle="Wrapped" defaultOutgoingResponseFormat="Json" helpEnabled="true" /> <enableWebScript /> </behavior> </endpointBehaviors> </behaviors> <bindings> <webHttpBinding> <binding name="webHttpBindingJsonP" crossDomainScriptAccessEnabled="true"/> </webHttpBinding> </bindings> <services> <service name="Adhesive.ComponentPerformance.Core.Service" behaviorConfiguration="ServiceBehaviour" > <endpoint address="http://localhost:8888/" binding="webHttpBinding" bindingConfiguration="webHttpBindingJsonP" behaviorConfiguration="HttpBehaviour" contract="Adhesive.ComponentPerformance.Core.Service" /> <endpoint address="http://localhost:8888/mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> </system.serviceModel>
话不多说,点击这里下载DEMO代码,在使用前建议你修改如下地方:
1)完善记录日志的地方
2)把配置改为你自己的配置服务
3)完善其它需要监测的开源组件
4)完善网站的分页等功能
最后预祝大家新年快乐!