在 Azure Web 角色中使用 SignalR 性能计数器
作者:Luke Latham
警告
本文档不适用于最新版本的 SignalR。 查看 ASP.NET Core SignalR。
SignalR 性能计数器用于监视 Azure Web 角色中的应用性能。 计数器由Microsoft Azure 诊断捕获。 使用 signalr.exe(用于独立应用或本地应用的工具)在 Azure 上安装 SignalR 性能计数器。 由于 Azure 角色是暂时性的,你需要将应用配置为在启动时安装和注册 SignalR 性能计数器。
先决条件
- Visual Studio 2015 或 2017
- Microsoft用于 Visual Studio 的 Azure SDK 注意:安装 SDK 后重启计算机。
- Microsoft Azure 订阅:若要注册免费的 Azure 试用版帐户,请参阅 Azure 免费试用。
创建公开 SignalR 性能计数器的 Azure Web 角色应用程序
打开“Visual Studio”。
在 Visual Studio 中,选择“文件”>“新建”>“项目”。
在“新建项目”对话框中,选择左侧的 Visual C#>Cloud 类别,然后选择 Azure 云服务模板。 将应用 命名为 SignalRPerfCounters ,然后选择“ 确定”。
注意
如果未看到 云 模板类别或 Azure 云服务 模板,则需要安装 Visual Studio 2017 的 Azure 开发 工作负载。 选择“新建项目”对话框左下角的“打开Visual Studio 安装程序链接以打开Visual Studio 安装程序。 选择 Azure 开发工作负荷,然后选择“修改”以开始安装工作负荷。
在 “新建Microsoft Azure 云服务 ”对话框中,选择 “ASP.NET Web 角色 ”,然后选择 > 用于将角色添加到项目的按钮。 选择“确定”。
在 “新建 ASP.NET Web 应用程序 - WebRole1 ”对话框中,选择 MVC 模板,然后选择“ 确定”。
在 解决方案资源管理器 中,打开 WebRole1 下的 diagnostics.wadcfgx 文件。
将文件的内容替换为以下配置并保存该文件:
<?xml version="1.0" encoding="utf-8"?> <DiagnosticsConfiguration xmlns="http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration"> <PublicConfig> <WadCfg> <DiagnosticMonitorConfiguration overallQuotaInMB="4096"> <DiagnosticInfrastructureLogs scheduledTransferLogLevelFilter="Error" /> <Logs scheduledTransferPeriod="PT1M" scheduledTransferLogLevelFilter="Error" /> <Directories scheduledTransferPeriod="PT1M"> <IISLogs containerName ="wad-iis-logfiles" /> <FailedRequestLogs containerName ="wad-failedrequestlogs" /> </Directories> <WindowsEventLog scheduledTransferPeriod="PT1M"> <DataSource name="Application!*[System[(Level=1 or Level=2 or Level=3)]]" /> <DataSource name="Windows Azure!*[System[(Level=1 or Level=2 or Level=3 or Level=4)]]" /> </WindowsEventLog> <CrashDumps containerName="wad-crashdumps" dumpType="Mini"> <CrashDumpConfiguration processName="WaIISHost.exe" /> <CrashDumpConfiguration processName="WaWorkerHost.exe" /> <CrashDumpConfiguration processName="w3wp.exe" /> </CrashDumps> <PerformanceCounters scheduledTransferPeriod="PT1M"> <PerformanceCounterConfiguration counterSpecifier="\Memory\Available MBytes" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\Web Service(_Total)\ISAPI Extension Requests/sec" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\Web Service(_Total)\Bytes Total/Sec" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\ASP.NET Applications(__Total__)\Requests/Sec" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\ASP.NET Applications(__Total__)\Errors Total/Sec" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\ASP.NET\Requests Queued" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\ASP.NET\Requests Rejected" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\Processor(_Total)\% Processor Time" sampleRate="PT3M" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Memory(w3wp)\% Time in GC" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Exceptions(w3wp)\# of Exceps Thrown / sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR LocksAndThreads(w3wp)\# of current logical Threads" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR LocksAndThreads(w3wp)\# of current physical Threads" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR LocksAndThreads(w3wp)\Current Queue Length" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR LocksAndThreads(w3wp)\Contention Rate / sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Memory(w3wp)\# Bytes in all Heaps" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Memory(w3wp)\# GC Handles" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\.NET CLR Memory(w3wp)\# of Pinned Objects" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connections Connected" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connections Reconnected" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connections Disconnected" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connections Current" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connection Messages Received Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connection Messages Sent Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connection Messages Received/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Connection Messages Sent/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Messages Received Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Messages Received/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Message Bus Messages Received/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Messages Published Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Messages Published/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Subscribers Current" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Subscribers Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Subscribers/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Allocated Workers" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Busy Workers" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Message Bus Topics Current" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: All Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: All/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: Hub Resolution Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: Hub Resolution/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: Hub Invocation Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: Hub Invocation/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: Tranport Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Errors: Transport/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Streams Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Streams Open" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Streams Buffering" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Errors Total" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Errors/Sec" sampleRate="PT10S" /> <PerformanceCounterConfiguration counterSpecifier="\SignalR(*)\Scaleout Send Queue Length" sampleRate="PT10S" /> </PerformanceCounters> </DiagnosticMonitorConfiguration> </WadCfg> <StorageAccount></StorageAccount> </PublicConfig> <PrivateConfig> <StorageAccount name="" key="" endpoint="" /> </PrivateConfig> <IsEnabled>true</IsEnabled> </DiagnosticsConfiguration>
从工具>NuGet 程序包管理器打开程序包管理器控制台。 输入以下命令以安装最新版本的 SignalR 和 SignalR 实用工具包:
install-package microsoft.aspnet.signalr install-package microsoft.aspnet.signalr.utils
将应用配置为在启动或回收时将 SignalR 性能计数器安装到角色实例中。 在解决方案资源管理器中,右键单击 WebRole1 项目并选择“添加新>文件夹”。 将新文件夹 命名为“启动”。
从项目文件夹>/SignalRPerfCounters/packages/Microsoft.AspNet.SignalR.Utils 复制signalr.exe文件(随 Microsoft.AspNet.SignalR.Utils 包<一起添加)。<在上一步中创建的 Startup 文件夹的版本>/工具。
在解决方案资源管理器中,右键单击“启动”文件夹,然后选择“添加>现有项”。 在出现的对话框中,选择 signalr.exe ,然后选择“ 添加”。
右键单击 创建的启动 文件夹。 选择“添加”>“新项”。 选择“常规”节点,选择“文本文件”,并将新项命名为SignalRPerfCounterInstall.cmd。 此命令文件会将 SignalR 性能计数器安装到 Web 角色中。
当 Visual Studio 创建 SignalRPerfCounterInstall.cmd 文件时,它将自动在主窗口中打开。 将文件的内容替换为以下脚本,然后保存并关闭该文件。 此脚本执行 signalr.exe,它将 SignalR 性能计数器添加到角色实例。
SET SignalR_LogDir=%~dp0Log\ MKDIR "%SignalR_LogDir%" cd %~dp0 signalr.exe ipc >> "%SignalR_LogDir%SignalR_Log.txt" 2>&1 net localgroup "Performance Monitor Users" "Network Service" /ADD >> "%SignalR_LogDir%NetworkAdd.txt" 2>&1
在解决方案资源管理器中选择signalr.exe文件。 在文件的 “属性”中,将 “复制到输出目录 ”以 “始终复制”。
对SignalRPerfCounterInstall.cmd文件重复上一步。
右键单击SignalRPerfCounterInstall.cmd文件,然后选择“打开使用”。 在出现的对话框中,选择“ 二进制编辑器 ”,然后选择“ 确定”。
在二进制编辑器中,选择文件中的任何前导字节并将其删除。 保存并关闭该文件。
打开 ServiceDefinition.csdef 并添加启动任务,该启动任务在服务启动时执行 SignalrPerfCounterInstall.cmd 文件:
<?xml version="1.0" encoding="utf-8"?> <ServiceDefinition name="SignalRPerfCounters" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2015-04.2.6"> <WebRole name="WebRole1" vmsize="Small"> <Startup> <Task commandLine="Startup\SignalRPerfCounterInstall.cmd" executionContext="elevated" taskType="background" /> </Startup> <Sites> <Site name="Web"> <Bindings> <Binding name="Endpoint1" endpointName="Endpoint1" /> </Bindings> </Site> </Sites> <Endpoints> <InputEndpoint name="Endpoint1" protocol="http" port="80" /> </Endpoints> </WebRole> </ServiceDefinition>
打开
Views/Shared/_Layout.cshtml
并删除文件末尾的 jQuery 捆绑脚本。<div class="container body-content"> @RenderBody() <hr /> <footer> <p>© @DateTime.Now.Year - My ASP.NET Application</p> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
添加一个 JavaScript 客户端,该客户端持续调用
increment
服务器上的方法。 打开Views/Home/Index.cshtml
内容并将其替换为以下代码:@{ ViewBag.Title = "Home Page"; } <script src="~/Scripts/jquery-1.10.2.min.js"></script> <script src="~/Scripts/jquery.signalR-2.2.1.min.js"></script> <script src="~/signalr/hubs" type="text/javascript"></script> <div id="body"> <section class="featured"> <div class="content-wrapper"> <p> Hello World! </p> <div style="font-size:large;"> My Counter: <span id="counter"></span> </div> </div> </section> <section class="content-wrapper main-content clear-fix"></section> </div> <script type="text/javascript"> $(document).ready(function () { var hub = $.connection.myHub; hub.client.sendResult = function (x) { console.log('sendResult(' + x + ')'); $("#counter").text(x); window.setTimeout(function () { hub.server.increment(x); }, 1000); }; $.connection.hub.connected = function () {}; $.connection.hub.disconnected = function () {}; $.connection.hub.stateChanged(function (change) { console.log('new State' + change.newState); if (change.newState === $.signalR.connectionState.disconnected) { $.connection.hub.start(); } if (change.newState === $.signalR.connectionState.reconnecting) { console.log('Re-connecting'); } else if (change.newState === $.signalR.connectionState.connected) { console.log('The server is online'); } }); $.connection.hub.error(function (error) { console.log('error ' + error); }); $.connection.hub.logging = true; $.connection.hub.reconnected(function () { console.log('Reconnected'); hub.server.increment(0); }); $.connection.hub.start().done(function () { console.log('hub started'); hub.server.increment(0); }); }); </script>
在名为 Hubs 的 WebRole1 项目中创建新文件夹。 右键单击解决方案资源管理器中的中心文件夹,然后选择“添加新>项”。 在“添加新项”对话框中,选择“Web>SignalR”类别,然后选择 SignalR 中心类(v2)项模板。 将新中心 命名为MyHub.cs 并选择“ 添加”。
MyHub.cs将自动在主窗口中打开。 将内容替换为以下代码,然后保存并关闭该文件:
using System.Threading.Tasks; using Microsoft.AspNet.SignalR; namespace WebRole1.Hubs { public class MyHub : Hub { public async Task Increment(int x) { await this.Clients.Caller.sendResult(x + 1); } } }
Crank.exe 是 SignalR 代码库提供的连接密度测试工具。 由于 Crank 需要持久连接,所以需要将一个连接到站点,以便在测试时使用。 向名为 PersistentConnections 的 WebRole1 项目添加新文件夹。 右键单击此文件夹,然后选择“添加>类”。 将新类文件 命名为MyPersistentConnections.cs 并选择“ 添加”。
Visual Studio 将在主窗口中打开 MyPersistentConnections.cs 文件。 将内容替换为以下代码,然后保存并关闭该文件:
using System.Threading.Tasks; using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Infrastructure; namespace WebRole1.PersistentConnections { public class MyPersistentConnection : PersistentConnection { protected override Task OnReceived(IRequest request, string connectionId, string data) { //Return data to calling user return Connection.Send(connectionId, data); } } }
Startup
使用类时,SignalR 对象在 OWIN 启动时启动。 打开或创建 Startup.cs, 并将内容替换为以下代码:using Microsoft.Owin; using Owin; using WebRole1.PersistentConnections; // Marks this class for automatic OWIN startup [assembly: OwinStartup(typeof(WebRole1.Startup))] namespace WebRole1 { public partial class Startup { public void Configuration(IAppBuilder app) { ConfigureAuth(app); // Only needed if "No Authentication" was not selected for the project app.MapSignalR(); app.MapSignalR<MyPersistentConnection>("/echo"); } } }
在上面的代码中,该
OwinStartup
属性将标记此类以启动 OWIN。 该方法Configuration
启动 SignalR。按 F5 在Microsoft Azure 模拟器中测试应用程序。
注意
如果在 MapSignalR 遇到 FileLoadException,请将 web.config 中的绑定重定向更改为以下内容:
<dependentAssembly> <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-2.0.2.0" newVersion="2.0.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-2.0.2.0" newVersion="2.0.0.0" /> </dependentAssembly>
等待大约一分钟。 在 Visual Studio 中打开 Cloud Explorer 工具窗口(查看>云资源管理器),然后展开路径。
(Local)/Storage Accounts/(Development)/Tables
双击 WADPerformanceCountersTable。 应在表数据中看到 SignalR 计数器。 如果未看到表,可能需要重新输入Azure 存储凭据。 可能需要选择“刷新”按钮才能在 Cloud Explorer 中查看表,或在打开的表窗口中选择“刷新”按钮以查看表中的数据。若要在云中测试应用程序,请更新 ServiceConfiguration.Cloud.cscfg 文件,并将该文件
Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString
设置为有效的Azure 存储帐户连接字符串。<?xml version="1.0" encoding="utf-8"?> <ServiceConfiguration serviceName="SignalRPerfCounters" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="4" osVersion="*" schemaVersion="2015-04.2.6"> <Role name="WebRole1"> <Instances count="1" /> <ConfigurationSettings> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=<account-name>;AccountKey=<account-key>" /> </ConfigurationSettings> </Role> </ServiceConfiguration>
将应用程序部署到 Azure 订阅。 有关如何将应用程序部署到 Azure 的详细信息,请参阅 如何创建和部署云服务。
稍等几分钟。 在 Cloud Explorer 中,找到上面配置的存储帐户,并在其中查找
WADPerformanceCountersTable
表。 应在表数据中看到 SignalR 计数器。 如果未看到表,可能需要重新输入Azure 存储凭据。 可能需要选择“刷新”按钮才能在 Cloud Explorer 中查看表,或在打开的表窗口中选择“刷新”按钮以查看表中的数据。
特别感谢 Martin Richard 在本教程中使用的原始内容。