Azure Web ロールでの SignalR パフォーマンス カウンターの使用
作成者: Luke Latham
警告
このドキュメントは、最新版の SignalR を対象としていません。 ASP.NET Core SignalR に関する記事を参照してください。
SignalR パフォーマンス カウンターは、Azure Web ロールでアプリのパフォーマンスを監視するために使用されます。 カウンターは Microsoft Azure Diagnostics によってキャプチャされます。 SignalR パフォーマンス カウンターは signalr.exe を使用して Azure にインストールします。これは、スタンドアロン アプリまたはオンプレミス アプリに使用されるのと同じツールです。 Azure ロールは一時的なものであるため、起動時に SignalR パフォーマンス カウンターをインストールして登録するようにアプリを構成します。
前提条件
- Visual Studio 2015 または 2017
- Microsoft Azure SDK for Visual Studio Note: SDK をインストールした後、コンピューターを再起動します。
- Microsoft Azure サブスクリプション: 無料の Azure 試用版アカウントにサインアップするには、「Azure 無料試用版」を参照してください。
SignalR パフォーマンス カウンターを公開する Azure Web ロール アプリケーションの作成
Visual Studio を開きます。
Visual Studio で、 [ファイル]>[新規]>[プロジェクト] の順に選択します。
[新しいプロジェクト] ダイアログ ボックスで、左側の [Visual C#]>[クラウド] カテゴリを選択し、[Azure クラウド サービス] テンプレートを選択します。 アプリに SignalRPerfCounters という名前を付け、[OK] を選択します。
Note
[クラウド] テンプレート カテゴリまたは [Azure クラウド サービス] テンプレートが表示されない場合は、Visual Studio 2017 用の [Azure 開発] ワークロードをインストール する必要があります。 [新しいプロジェクト] ダイアログの左下にある [Visual Studio インストーラーを開く] リンクを選択して、Visual Studio インストーラーを開きます。 [Azure 開発] ワークロードを 選択し、[変更] を選択してワークロードのインストールを開始します。
[新しい Microsoft Azure クラウド サービス] ダイアログで、[ASP.NET Web ロール] を選択し、> ボタンを選択してロールをプロジェクトに追加します。 [OK] を選択します。
[新しい ASP.NET Web アプリケーション - WebRole1] ダイアログボックスで、MVC テンプレートを選択し、[OK] を選択します。
ソリューション エクスプローラーで、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 Package Manager] からパッケージ マネージャー コンソールを開きます。 最新バージョンの SignalR と SignalR ユーティリティ パッケージをインストールするには、次のコマンドを入力します。
install-package microsoft.aspnet.signalr install-package microsoft.aspnet.signalr.utils
起動時またはリサイクル時に SignalR パフォーマンス カウンターをロール インスタンスにインストールするようにアプリを構成します。 ソリューション エクスプローラーで、WebRole1 プロジェクトを右クリックし、[追加]>[新しいフォルダー] を選択します。 新しいフォルダーに Startup という名前を付けます。
<プロジェクト フォルダー>/ SignalRPerfCounters/packages/Microsoft.AspNet.SignalR.Utils.<バージョン>/tools から signalr.exe ファイル (Microsoft.AspNet.SignalR.Utils パッケージと共に追加) を前の手順で作成した Startup フォルダーへコピーします。
ソリューション エクスプローラーで、Startup フォルダーを 右クリックし、[追加]>[既存の項目] を選択します。 表示されたダイアログで、signalr.exe を選択し、[追加] を選択します。
作成した Startup フォルダーを右クリックします。 [追加]>[新しい項目] の順に選択します。 [全般] ノードを選択し、[テキスト ファイル] を選択し、新しい項目に SignalRPerfCounterInstall.cmd と名前を付けます。 このコマンド ファイルは、SignalR パフォーマンス カウンターを Web ロールにインストールします。
Visual Studio によって SignalRPerfCounterInstall.cmd ファイルが作成されると、メイン ウィンドウで自動的に開きます。 ファイルの内容を次の XML に置き換え、ファイルを保存して閉じます。 このスクリプトは、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 ファイルを右クリックし、[ファイルを開く] を選択します。 表示されたダイアログで、[バイナリ エディター] を選択 し、[OK] を選択します。
バイナリ エディターで、ファイル内の先頭のバイトを選択して削除します。 ファイルを保存して閉じます。
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>
サーバー上で
increment
メソッドを継続的に呼び出す JavaScript クライアントを追加します。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>
WebRole1 プロジェクトに Hubs という名前の新しいフォルダーを作成します。 ソリューション エクスプローラーで Hubs フォルダーを右クリックし、[追加]>[新しい項目] を選択 します。 [新しい項目の追加] ダイアログ ボックスで、[Web]>[Signal] Rカテゴリを選択し、[SignalR Hub クラス (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 Emulator でアプリケーションをテストします。
Note
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>
約 1 分待ちます。 Visual Studio で Cloud Explorer ツール ウィンドウを開き ([表示]>[クラウド エクスプローラー])、パス
(Local)/Storage Accounts/(Development)/Tables
を展開します。 WADPerformanceCountersTable をダブルクリックします。 テーブル データに SignalR カウンターが表示されるはずです。 テーブルが表示されない場合は、Azure Storage の資格情報を再入力が必要な場合があります。 Cloud Explorer でテーブルを表示するには [更新] ボタンを選択するか、開いているテーブル ウィンドウの [更新] ボタンを選択してテーブル内のデータを表示することが必要な場合があります。クラウドでアプリケーションをテストするには、ServiceConfiguration.Cloud.cscfg ファイルを更新し、
Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString
を有効な Azure Storage アカウント接続文字列に設定します。<?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 Storage の資格情報を再入力が必要な場合があります。 Cloud Explorer でテーブルを表示するには [更新] ボタンを選択するか、開いているテーブル ウィンドウの [更新] ボタンを選択してテーブル内のデータを表示することが必要な場合があります。
このチュートリアルで使用されている元のコンテンツを作成した Martin Richard に感謝します。