集成 WCF 和 HTML5 来监控系统资源
监控系统的整体架构。
介绍
本文介绍了如何集成 Microsoft .NET 技术和最新的 Web 工具(如 HTML5、jQuery 和 Flot)来监控和展示系统资源数据(例如 CPU 使用率和内存负载)。
所提供的解决方案可以作为扩展应用程序的骨架,用于管理和监控远程设备。下图是基于 WCF 服务的整体架构:每个远程设备公开一个由 Windows 服务托管的 WCF 服务,所有来自远程设备的信息由 IIS 托管的 Web 应用程序收集并公开。
以下的实现仅监控一台设备(即 Web 服务器 IIS 所在的同一台设备),但只需添加几行代码即可轻松扩展到监控多台设备。用于检索系统资源使用情况的代码基于我编写的一个 C++ COM 对象,并在此提供为 DLL 文件。
背景
提供的代码打包在 Visual Studio 2012 解决方案中,包含 Windows 服务项目和 Web 应用程序项目。需要具备 WCF、jQuery 和 HTML5 的基础知识。此外,主网页使用了 Flot,一个用于 jQuery 的 JavaScript 图表库(更多信息请参阅 http://www.flotcharts.org/)。
主要内容是关于 WCF 服务的配置,Web 中的 Ajax 支持以及 Windows 服务中的 wsHttpBinding。要使用 COM 对象 SystemManager 提供的服务,只需在您要监控的机器上注册LogthetaSystemManagement.dll(请参阅上方)。
设置解决方案并运行代码
“SystemMonitor”解决方案包含两个项目:
- SystemManagementService:一个托管 WCF 服务并收集机器数据(CPU 使用率和内存负载)的 Windows 服务。
- SystemMonitor.WebUI:一个 Web UI,托管一个 WCF 服务,该服务轮询安装在远程设备(在此示例中,与 Web 服务器在同一台机器上)上的 Windows 服务的数据,并在网页上绘制图表。
要编译并运行解决方案,请按照以下步骤操作:
- 注册 SystemManagementService 项目中包含的Logtheta.SystemManagement.dll COM 组件:打开 Shell 并运行 regsvr32 [Path]\Logtheta.SystemManagement.dll。之后,您应该能在 dcomcnfg 中看到该组件。
- 全部重新生成
- 运行 SystemManagementService 项目中包含的 InstallService.cmd 文件来安装 Windows 服务。此批处理文件会安装并启动服务。之后,您将有一个 HTTP WCF 服务响应在App.config中配置的 URL。
- 将 SystemMonitor.WebUI 注册为 Web 应用程序(属性 > Web > 创建虚拟目录)。
- 运行解决方案
使用代码
public class SystemManagementService : ISystemManagementService
{
/// <summary>
/// Retrieve CPU usages
/// </summary>
/// <returns></returns>
public double GetCPUUsages()
{
ISystemManager systemManager = new SystemManager();
return systemManager.GetCPUUsages();
}
/// <summary>
/// Retrieve System Memory usage
/// </summary>
/// <returns></returns>
public double GetMemoryUsage()
{
ISystemManager systemManager = new SystemManager();
uint availableMemory = systemManager.GetAvailableRAM();
uint totalMemory = systemManager.GetTotalRAM();
return (1 - ((double)availableMemory) / totalMemory) * 100;
}
}
此代码使用Logtheta.SystemManagement.dll中的SystemManger
互操作类来检索 CPU 使用率和内存使用率。
该服务封装在一个 Windows 服务应用程序中,以避免在远程设备上安装 IIS。
您可以通过更改App.config中指定的“baseAddress”来更改 WCF 服务响应的端口:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<services>
<service name="Logtheta.SystemManagementService">
<host>
<baseAddresses>
<add baseAddress="https://:8000/LogthetaServices/SystemManagementService"/>
</baseAddresses>
</host>
<!-- this endpoint is exposed at the base address provided by host:
https://:8000/LogthetaServices/SystemManagementService -->
<endpoint address="" binding="wsHttpBinding"
contract="Logtheta.ISystemManagementService"/>
<!-- the mex endpoint is exposed at
https://:8000/LogthetaServices/SystemManagementService/mex -->
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>
<!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
请注意,该服务使用的是 wsHttpBinding。
一旦远程设备上的 Windows 服务启动并运行,您就可以从 Web 应用程序进行连接。在web.config中,您可以找到 WCF 客户端定义:
<client>
<endpoint address="https://:8000/LogthetaServices/SystemManagementService"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ISystemManagementService"
contract="SystemManagementService.ISystemManagementService"
name="SystemManagementService">
<identity>
<servicePrincipalName value="host/VaioGiuseppe" />
</identity>
</endpoint>
</client>
如果需要,请进行更改。为了展示数据,我们需要一个启用了 WCF 服务 Ajax,以便我们可以使用 jQuery 以 JSON 格式检索数据:
[ServiceBehavior]
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class SystemMonitorService : ISystemMonitorService
{
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public SystemResources GetSystemResources()
{
//@TODO: change this in order to retrieve the uri from
//DB if you want to manage mul tiple systems monitor
Uri endPointUri =
new Uri("https://:8000/LogthetaServices/SystemManagementService");
SystemManagementServiceClient systemManagementService =
GetSystemManagementServiceClient(endPointUri);
double cpuUsages = systemManagementService.GetCPUUsages();
double memoryUsage = systemManagementService.GetMemoryUsage();
return new SystemResources { CPUUsages = cpuUsages,
MemoryUsage = memoryUsage , Hostname = "localhost"};
}
private SystemManagementServiceClient GetSystemManagementServiceClient(Uri endPointUri)
{
Binding binding = new WSHttpBinding();
EndpointAddress endpoint = new EndpointAddress(endPointUri);
SystemManagementServiceClient client = new SystemManagementServiceClient(binding, endpoint);
return client;
}
}
请注意,主方法“GestSystemResources
”已装饰,以便使用 JSON 格式。如果您对远程 WCF 服务配置进行了任何更改,则需要相应地更改 endPoiuntUri
变量。
现在我们可以使用 AJAX 调用已启用 Ajax 的 WCF 服务。Web 应用程序“Scripts”文件夹中的app.js文件包含了检索数据、设置 Flot 控件和定期绘制数据的所有代码。App.js中的主要代码是:
function getData() {
$.ajax({
type: "GET",
url: serviceUrl,
cache: false,
data: {},
contentType: "application/json; charset=utf-8",
dataType: "text",
success: OnSuccess,
error: OnError
});
function OnSuccess(response) {
//console.log("OnSuccess data");
var s = JSON.parse(response);
//draw cpu and memory data
cpuPlot.setData([cpuPlotData.buildData(s.d.CPUUsages)]);
cpuPlot.draw();
memPlot.setData([memPlotData.buildData(s.d.MemoryUsage)]);
memPlot.draw();
setTimeout(updateStatistics, updateInterval);
}
function OnError(response) {
var r = JSON.parse(response);
alert("Error");
}
};
请注意,AJAX 调用中的 dataType
必须是“text”,这样您才能在“OnSuccess”回调中通过 JSON.parse
方法解析结果。
值得关注的点
您可以扩展此解决方案来监控多台设备,只需添加一个简单的 SQL Server 数据库和 Entity Framework 来访问数据。您始终需要在远程机器上安装 Windows 服务,但即使未安装 IIS,您也可以通过 HTTP 检索数据。
历史
- 2013 年 6 月 4 日:首次发布。