SignalR パフォーマンス
作成者: Patrick Fletcher
警告
このドキュメントは、最新版の SignalR を対象としていません。 ASP.NET Core SignalR に関する記事を参照してください。
このトピックでは、SignalR アプリケーションのパフォーマンスを設計、測定、改善する方法について説明します。
このトピックで使用されるソフトウェアのバージョン
- Visual Studio 2013
- .NET 4.5
- SignalR バージョン 2
このトピックの以前のバージョン
SignalR の以前のバージョンの詳細については、「SignalR の以前のバージョン」を参照してください。
質問とコメント
このチュートリアルの感想、改善に関するフィードバックをページの下部にあるコメント欄にお寄せください。 チュートリアルに直接関連しない質問がある場合は、ASP.NET SignalR フォーラムまたは StackOverflow.com に投稿できます。
SignalR のパフォーマンスとスケーリングに関する最近のプレゼンテーションについては、ASP.NET SignalR を使ったリアルタイム Web のスケーリングに関するページを参照してください。
このトピックは、次のセクションで構成されています。
- 設計上の考慮事項
- SignalR サーバーのパフォーマンスの調整
- パフォーマンスに関する問題のトラブルシューティング
- SignalR パフォーマンス カウンターの使用
- その他のパフォーマンス カウンターの使用
- その他のリソース
設計上の考慮事項
このセクションでは、不要なネットワーク トラフィックの生成によってパフォーマンスが低下しないように、SignalR アプリケーションの設計時に実装できるパターンについて説明します。
メッセージ頻度の調整
高頻度でメッセージを送信するアプリケーション (リアルタイム ゲーム アプリケーションなど) であっても、ほとんどのアプリケーションは 1 秒間に数個以上のメッセージを送信する必要はありません。 各クライアントが生成するトラフィック量を減らすために、固定レート未満の頻度でメッセージをキューに格納して送信するメッセージ ループを実装できます (つまり、送信すべきメッセージがその時間間隔にある場合、毎秒一定数までのメッセージが送信されます)。 (クライアントとサーバーの両方から) メッセージを特定のレートに調整するサンプル アプリケーションについては、SignalR を使った高頻度リアルタイムに関する記事を参照してください。
メッセージ サイズの縮小
シリアル化されたオブジェクトのサイズを小さくすることで、SignalR メッセージのサイズを小さくすることができます。 サーバー コードで、送信する必要のないプロパティを含むオブジェクトを送信する場合は、JsonIgnore
属性を使ってそれらのプロパティがシリアル化されないようにします。 プロパティの名前もメッセージに格納されます。プロパティの名前は、JsonProperty
属性を使って短縮できます。 次のコード サンプルは、クライアントへの送信からプロパティを除外する方法と、プロパティ名を短縮する方法を示しています。
クライアントに送信されるデータを除外する JsonIgnore 属性と、メッセージ サイズを削減する JsonProperty 属性を示す .NET サーバー コード
using Newtonsoft.Json;
using System;
public class ShapeModel
{
[JsonProperty("l")]
public double Left { get; set; }
[JsonProperty("t")]
public double Top { get; set; }
// We don't want the client to get the "LastUpdatedBy" property
[JsonIgnore]
public string LastUpdatedBy { get; set; }
}
クライアント コードの読みやすさと保守のしやすさを維持するために、メッセージの受信後に、短縮されたプロパティ名を人間にとってわかりやすい名前に再マップできます。 次のコード サンプルは、メッセージ コントラクト (マッピング) を定義し、reMap
関数を使ってそのコントラクトを最適化されたメッセージ クラスに適用することにより、短縮名を長い名前に再マップする可能な方法の 1 つを示しています。
短縮されたプロパティ名を人間が判読できる名前に再マップするクライアント側 JavaScript コード
function reMap(smallObject, contract) {
var largeObject = {};
for (var smallProperty in contract) {
largeObject[contract[smallProperty]] = smallObject[smallProperty];
}
return largeObject;
}
var shapeModelContract = {
l: "left",
t: "top"
};
myHub.client.setShape = function (shapeModelSmall) {
var shapeModel = reMap(shapeModelSmall, shapeModelContract);
// shapeModelSmall has "l" and "t" properties but after remapping
// shapeModel now has "left" and "top" properties
};
同じ方法を使って、クライアントからサーバーへのメッセージで名前を短縮することもできます。
メッセージ オブジェクトのメモリ占有領域 (つまり、メッセージに使われるメモリの量) を削減すると、パフォーマンスも向上します。 たとえば、int
の全範囲が必要ない場合は、代わりに short
または byte
を使用できます。
メッセージはサーバー メモリのメッセージ バスに格納されるため、メッセージのサイズを小さくすることでサーバー メモリの問題も解決できます。
SignalR サーバーのパフォーマンスの調整
次の構成設定を使って、SignalR アプリケーションのパフォーマンスが向上するようにサーバーを調整できます。 ASP.NET アプリケーションのパフォーマンスを向上させる一般的な方法については、「ASP.NET のパフォーマンスの向上」を参照してください。
SignalR の構成設定
DefaultMessageBufferSize: SignalR は、既定で 1 つの接続でハブごとに 1000 個のメッセージをメモリに保持します。 大きなメッセージが使われている場合、これによってメモリの問題が生じる可能性がありますが、この値を減らすことで軽減できます。 この設定は、ASP.NET アプリケーションの
Application_Start
イベント ハンドラー、またはセルフホステッド アプリケーションの OWIN スタートアップ クラスのConfiguration
メソッドで設定できます。 次のサンプルは、使われるサーバー メモリ量を減らす目的で、アプリケーションのメモリ占有領域を減らすためにこの値を減らす方法を示しています。既定のメッセージ バッファー サイズを減らすための Startup.cs 内の .NET サーバー コード
public class Startup { public void Configuration(IAppBuilder app) { // Any connection or hub wire up and configuration should go here GlobalHost.Configuration.DefaultMessageBufferSize = 500; app.MapSignalR(); } }
IIS の構成設定
アプリケーションあたりの最大同時要求数: 同時 IIS 要求の数を増やすと、要求の処理に使用できるサーバー リソースが増えます。 既定値は 5000 です。この設定を増やすには、管理者特権でのコマンド プロンプトで次のコマンドを実行します。
cd %windir%\System32\inetsrv\ appcmd.exe set config /section:system.webserver/serverRuntime /appConcurrentRequestLimit:10000
ApplicationPool QueueLength: これは、Http.sys がアプリケーション プールのキューに格納する要求の最大数です。 キューがいっぱいになると、新しい要求は 503 "Service Unavailable" 応答を受け取ります。 既定値は 1000 です。
アプリケーションをホストしているアプリケーション プール内のワーカー プロセスのキュー長を短くすると、メモリ リソースを節約できます。 詳細については、アプリケーション プールの管理、調整、構成に関する記事を参照してください。
ASP.NET の構成設定
このセクションには、aspnet.config
ファイルで設定できる構成設定について説明します。 このファイルは、プラットフォームに応じて、次の 2 つの場所のいずれかにあります。
%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet.config
%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet.config
次のような ASP.NET 設定で SignalR のパフォーマンスが向上する可能性があります。
CPU あたりの最大同時要求数: この設定を増やすと、パフォーマンスのボトルネックが軽減される可能性があります。 この設定を増やすには、次の構成設定を
aspnet.config
ファイルに追加します。<?xml version="1.0" encoding="UTF-8" ?> <configuration> <system.web> <applicationPool maxConcurrentRequestsPerCPU="20000" /> </system.web> </configuration>
要求キューの制限: 接続の合計数が
maxConcurrentRequestsPerCPU
設定を超えると、ASP.NET はキューを使って要求の調整を開始します。 キューのサイズを増やすには、requestQueueLimit
設定を増やします。 これを行うには、次の構成設定を (aspnet.config
ではなく)config/machine.config
のprocessModel
ノードに追加します。<processModel autoConfig="false" requestQueueLimit="250000" />
パフォーマンスに関する問題のトラブルシューティング
このセクションでは、アプリケーションのパフォーマンスのボトルネックを見つける方法について説明します。
WebSocket が使われていることを確認する
SignalR はクライアントとサーバー間の通信にさまざまなトランスポートを使用できますが、WebSocket はパフォーマンスに大きな利点があるため、クライアントとサーバーがサポートしている場合は使うことをお勧めします。 クライアントとサーバーが WebSocket の要件を満たしているかどうかを確認するには、「トランスポートとフォールバック」を参照してください。 アプリケーションでどのトランスポートが使われているかを確認するには、ブラウザー開発者ツールを使い、ログを調べて接続にどのトランスポートが使われているかを確認します。 Internet Explorer と Chrome のブラウザー開発ツールの使用方法については、「トランスポートとフォールバック」を参照してください。
SignalR パフォーマンス カウンターの使用
このセクションでは、Microsoft.AspNet.SignalR.Utils
パッケージに含まれる SignalR パフォーマンス カウンターを有効にして使う方法について説明します。
signalr.exe のインストール
SignalR.exe というユーティリティを使って、パフォーマンス カウンターをサーバーに追加できます。 このユーティリティをインストールするには、以下の手順を実行します。
Visual Studio で、[ツール]>[NuGet パッケージ マネージャー]>[ソリューションの NuGet パッケージの管理] を選びます
signalr.utils を検索し、[インストール] を選びます。
使用許諾契約に同意してパッケージをインストールします。
SignalR.exe が
<project folder>/packages/Microsoft.AspNet.SignalR.Utils.<version>/tools
にインストールされます。
SignalR.exe を使ったパフォーマンス カウンターのインストール
SignalR パフォーマンス カウンターをインストールするには、管理者特権でのコマンド プロンプトで、次のパラメーターを指定して SignalR.exe を実行します。
SignalR.exe ipc
SignalR パフォーマンス カウンターを削除するには、管理者特権でのコマンド プロンプトで、次のパラメーターを指定して SignalR.exe を実行します。
SignalR.exe upc
SignalR パフォーマンス カウンター
ユーティリティ パッケージを使うと、次のパフォーマンス カウンターがインストールされます。 [合計] カウンターには、アプリケーション プールまたはサーバーが最後に再起動されてからのイベント数が測定されます。
接続メトリック
次のメトリックは、発生する接続有効期間イベントを測定します。 詳細については、接続有効期間イベントの概要と処理に関する記事を参照してください。
- Connections Connected
- Connections Reconnected
- Connections Disconnected
- Connections Current
Message metrics
次のメトリックは、SignalR によって生成されたメッセージ トラフィックを測定します。
- Connection Messages Received Total
- Connection Messages Sent Total
- Connection Messages Received/Sec
- Connection Messages Sent/Sec
Message bus metrics
次のメトリックは、内部 SignalR メッセージ バス (すべての受信および送信 SignalR メッセージが配置されるキュー) を経由するトラフィックを測定します。 メッセージは、送信またはブロードキャストされると "発行済み" になります。 このコンテキストでの "Subscriber" とは、メッセージ バス上のサブスクライブです。これは、クライアント数にサーバー自体を加えた数に等しい必要があります。 "Allocated Worker" は、アクティブな接続にデータを送信するコンポーネントです。"Busy Worker" は、アクティブにメッセージを送信しているものです。
- Message Bus Messages Received Total
- Message Bus Messages Received/Sec
- Message Bus Messages Published Total
- Message Bus Messages Published/Sec
- Message Bus Subscribers Current
- Message Bus Subscribers Total
- Message Bus Subscribers/Sec
- Message Bus Allocated Workers
- Message Bus Busy Workers
- Message Bus Topics Current
エラー指標
次のメトリックは、SignalR メッセージ トラフィックによって生成されたエラーを測定します。 ハブ解決エラーは、ハブまたはハブ メソッドを解決できない場合に発生します。 ハブ呼び出しエラーは、ハブ メソッドの呼び出し中にスローされる例外です。 トランスポート エラーは、HTTP 要求または応答中にスローされる接続エラーです。
- Errors: All Total
- Errors: All/Sec
- Errors: Hub Resolution Total
- Errors: Hub Resolution/Sec
- Errors: Hub Invocation Total
- Errors: Hub Invocation/Sec
- Errors: Transport Total
- Errors: Transport/Sec
Scaleout metrics
次のメトリックは、スケールアウト プロバイダーによって生成されたトラフィックとエラーを測定します。 このコンテキストでの "Stream" とは、スケールアウト プロバイダーによって使われるスケール ユニットです。これは、SQL Server を使う場合はテーブル、Service Bus を使う場合はトピック、Redis を使う場合はサブスクリプションです。 各ストリームは順序付けられた読み取りと書き込み操作を保証します。1 つのストリームがスケールのボトルネックになる可能性があるため、ストリーム数を増やすことでボトルネックを減らすことができます。 複数のストリームが使われている場合、SignalR は、特定の接続から送信されるメッセージが順序どおりであることを保証する方法で、これらのストリーム全体にメッセージを自動的に分散 (シャード) します。
MaxQueueLength 設定を使って、SignalR によって維持されるスケールアウト送信キューの長さを制御します。 0 より大きい値に設定すると、すべてのメッセージが送信キューに配置され、構成されたメッセージング バックプレーンに一度に 1 つずつ送信されます。 構成済みの長さをキューのサイズが超えると、キュー内のメッセージ数が再度設定値を下回るまで、後続の送信呼び出しは InvalidOperationException で即時に失敗します。 実装されたバックプレーンには、通常、独自のキューまたはフロー制御が設定されているため、キューは既定では無効になっています。 SQL Server の場合、接続プールにより、一度に実行される送信数は効果的に制限されます。
既定では、SQL Server と Redis には 1 つのストリームのみが使われ、Service Bus には 5 つのストリームが使われ、キューは無効になっていますが、これらの設定は SQL Server と Service Bus の構成を使って変更できます。
SQL Server バックプレーンのテーブル数とキューの長さを構成するための .NET サーバー コード
var connectionString = "(your connection string)";
var config = new SqlScaleoutConfiguration(connectionString) {
TableCount = 3,
MaxQueueLength = 50 };
GlobalHost.DependencyResolver.UseSqlServer(config);
Service Bus バックプレーンのトピック数とキューの長さを構成するための .NET サーバー コード
string connectionString = "(your connection string)";
var config = new ServiceBusScaleoutConfiguration(connectionString, "YourAppName") {
TopicCount = 3,
MaxQueueLength = 50 };
GlobalHost.DependencyResolver.UseServiceBus(config);
バッファリング ストリームは、障害状態になったストリームです。ストリームが障害状態になると、ストリームに障害がなくなるまで、バックプレーンに送信されたすべてのメッセージは直ちに失敗します。 "Send Queue Length" は、投稿済みでまだ送信されていないメッセージ数です。
- Scaleout Message Bus Messages Received/Sec
- Scaleout Streams Total
- Scaleout Streams Open
- Scaleout Streams Buffering
- Scaleout Errors Total
- Scaleout Errors/Sec
- Scaleout Send Queue Length
これらのカウンターの測定内容の詳細については、「Azure Service Bus による SignalR スケールアウト」を参照してください。
その他のパフォーマンス カウンターの使用
次のパフォーマンス カウンターは、アプリケーションのパフォーマンスを監視する場合にも役立ちます。
[メモリ]
- .NET CLR Memory\# bytes in all Heaps (for w3wp)
ASP.NET
- ASP.NET\Requests Current
- ASP.NET\Queued
- ASP.NET\Rejected
CPU
- Processor Information\Processor Time
TCP/IP
- TCPv6/Connections Established
- TCPv4/Connections Established
Web サービス
- Web Service\Current Connections
- Web Service\Maximum Connections
スレッド化
- .NET CLR Locks And Threads\# of current logical Threads
- .NET CLR Locks And Threads\# of current physical Threads
その他の参照情報
ASP.NET のパフォーマンスの監視と調整の詳細については、次のトピックを参照してください。