400 likes | 482 Views
SignalR ブートキャンプ. SignalR ブートキャンプ. 地理冗長の中心で Azure 愛を 叫ぶ in 名古屋 2014.3.1 Kouji Matsui (@kekyo2). 自己紹介. Kouji Matsui (@kekyo2) 名古屋のコミュニティ、 MiCoCi のメンバーです。 「なごやこわい」のメンバーではありません w アーキテクトやってます。あと、スクラム道もはじめました。. リアルタイム通信、始まる. サーバ ーとクライアントを接続して、何か連携できることがしたいよね!! TCP とかでリアルタイム通信! ゲーム!!
E N D
SignalRブートキャンプ SignalRブートキャンプ 地理冗長の中心でAzure愛を叫ぶ in 名古屋 2014.3.1 Kouji Matsui (@kekyo2)
自己紹介 • Kouji Matsui (@kekyo2) • 名古屋のコミュニティ、MiCoCiのメンバーです。 • 「なごやこわい」のメンバーではありませんw • アーキテクトやってます。あと、スクラム道もはじめました。
リアルタイム通信、始まる • サーバーとクライアントを接続して、何か連携できることがしたいよね!! TCPとかでリアルタイム通信! ゲーム!! • でも、基本、クライアントの人だから、サーバーわかんないんだ、何もかも(遠い目) • 「SignalR」ってライブラリを使えば、簡単にリアルタイム通信出来るよ!! サーバーの管理なんて、Windows Azureに任せちゃえばいい!
SignalRが使えると? • SignalRおいしい? それ何? • TCPでソケット繋いでどうとか、通信電文がどうだとか、面倒な事は殆ど自動でやってくれる! → だから、本来実現したかったことに集中出来る!! • ほうほう、それで? 簡単実現!
SignalRがやってくれる事 サーバーのメソッドを呼び出す感覚でコードを書けるワ Jsonによる通信(プレーンではない) 通信手段の自動的な選択 HTTPやWebSocketなど
通信を抽象化 ・同報通知も可能 ・特定端末にだけ送信 ・グルーピングして送信
サポートする環境は? Windows PC / IE / Chrome / etc... Windows Phone / Tablets... Windows Server
SignalR使おうとしたら、OWINって? • Open Web Interface for .NET • ウェブサーバー向けの新しいフレームワーク • えぇー?またフレームワーク増えたの?! • まぁ、そうなんですが、ASP.NET WebFormやMVCとは位置づけがちょっと違います。SignalRはこれに乗っかります。 • OWINの詳細は知らなくても大丈夫ですが、どんなものなのか、少しだけ紹介します。 • 大丈夫、NuGetを使えば簡単に導入できます!
見せてもらう必要がありそうネ、全て取り払った 最小のコードとやらを • いくらNuGetで簡単にライブラリを導入できても、一度にあまりに大量のコードが追加されると、何が何だか... orz • では、「スクラッチ」に近い状態でのコードをお見せします。
論よりOWIN 似たようなパッケージが沢山公開されているので、注意! • OWINの導入は超簡単。NuGet一発!”Install-Package Microsoft.Owin.Host.SystemWeb” (2.0.2) Microsoft.Owin.Host.SystemWeb ASP.NETでOWINを動作可能にする Microsoft.Owin Owin
論よりOWIN • 「OWINスタートアップクラス」を追加 スタートアップクラスとOwinを結びつける
Hello! OWIN IOwinContext – HttpContextの抽象インターフェイス
何がどうなってる? • ASP.NETウェブフォームでは、HttpContextを受け取るまでに、System.Web.UI.Pageからページを生成する必要がありました。 • Pageクラスはデカい、ページレンダリングの余分なコードが多い。シンプルではない。例のように、Hello World的コードであっても、非常に大がかりな仕掛けが動作します。 • OWINは非常にシンプル。IOwinContextを受け取って動作するまでに必要な、複雑なフレームワーク構造は存在しません。
OWINでSignalRのセットアップ • NuGetで一発“Install-Package Microsoft.AspNet.SignalR.SystemWeb” (2.0.2) Microsoft.Owin Microsoft.Owin.Host.SystemWeb Owin Microsoft.AspNet.SignalR.SystemWeb Microsoft.AspNet.SignalR.Core
Web.configがおかしい... • 2.0.2をNuGetで導入時に、Web.configに不正なエントリーが追加されるので、手動で修正が必要。 アセンブリバージョンの3番目要素を広くする。この例では「99」に設定した
OWINでSignalRのセットアップ • OWINスタートアップクラスで、SignalRにコンテキストを転送する Microsoft.AspNet.SignalR.Core.dll Owin.OwinExtensions.MapSignalR() コンテキストパイプラインをSignalRに転送
準備完了 後はハブとメソッドを 決めるだけネ?
何を作る? • ホワイトボードアプリ • Windows Phone・Silverlight・WPFでリアルタイム白板会議 手書きのポリライン座標を送受信
まずはサーバー側から • ハブクラス→サーバーAPIの端点。このクラスからAPIメソッドを公開。 SignalR クライアント SignalRハブ “SharedWhiteBoardHub” ハブ上のメソッド群 “PlaceLine”
ハブクラスの実装 • ハブクラス→サーバーAPIの端点。このクラスからAPIメソッドを公開。 Microsoft.AspNet.SignalR.Hubクラス Hubクラスを継承すると、自動的に認識される 外部から呼び出されるメソッドの定義 接続中の全てのクライアントの「DrawLine」メソッドにコールバック
送受信データの定義 • 文字列や数値が1~4個なら、直接引数に定義できます。 • それ以上の複雑なデータをやり取りする場合は、エンティティクラスを定義して、このクラスごと送受信します。 • エンティティクラスは、DataContract属性で修飾した、パブリックな値の入れ物とします。 • 最終的に、Json.NETによってJsonとの相互変換が行われる事に注意。 • 全く同じクラスをサービス側とクライアント側の両方で定義しても良いが、どうせならPortable Class Libraryにして共用しよう。
送受信データの定義 DataContract属性で修飾したクラス DataMember属性で修飾したパブリックなプロパティ 必要なだけメンバを定義可能。Jsonで表現可能かどうかは考慮する必要がある。
クライアント側は? • クライアントから、ハブのメソッドを呼び出す • サーバーからのコールバックを受信する PlaceLine() “SharedWhiteBoardHub” DrawLine()
クライアントの実装 (NuGet導入) • まずはクライアントにNuGetでライブラリを導入 (2.0.2)“Install-Package Microsoft.AspNet.SignalR.Client” • あるいは、Portable Class Library版 (2.0.1)“Install-Package Microsoft.AspNet.SignalR.Client.Portable”(これは私が作って配布したものです。SL4/WP7.5にも対応、但し、WebSocket接続は出来ません) • パッケージ依存は多いので、図での説明は省略します (汗BCL, Json.NET, HttpClientなど
クライアントの実装 (ハブへの接続) HubConnectionクラスが、ハブへの接続を管理する CreateHubProxyで、サーバーのハブクラスのプロキシ(代理)インスタンスを生成する。 型はIHubProxyインターフェイス。 クライアントの動作を開始
クライアントの実装 (ハブのメソッドを実行) LineInformationクラス(エンティティ)に、送信する情報を代入 保存しておいたハブプロキシのInvokeメソッドを呼び出す。 メソッド名:「PlaceLine」 必要ならawaitする
クライアントの実装 (コールバック1) コールバックするスレッドはワーカースレッドなので、UIを操作するにはUIスレッド(メインスレッド)へのマーシャリングが必要。
クライアントの実装 (コールバック2) Start前に、コールバックメソッドを登録する。 On<T>のT型が、受信する引数
Try it! http://signalrbootcamp.cloudapp.net/WhiteBoard.html デモ 上手く行かなかったら... わかってるわネ?
IIS ExpressからAzureへ • SignalRはもちろん、Azure上で使えます。 • WebSocketで接続OKです。 • OS Family 3以降が必要(Windows Server 2012) • クライアント側が.NET4.5以上かつWindows 8以上 WireSharkでWebSocketパケットを確認
AzureTips • 標準的な使用方法は、クラウドサービス(Webロール) • ワーカーロールでも使用可能。OWINのホストをワーカーロールで実行する(NuGetで、OWIN hostで検索すると、色々出てきます)。 • Webサイトでも使用可。但し、WebSocketで接続する場合は、最大接続数の制限に注意。 • Free: (5) concurrent connections per website instance • Shared: (35) concurrent connections per website instance • Standard: (350) concurrent connections per website instance • http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx
WebSocketは高速だけど... • WebSocketはHTTPで接続した際のTCPソケットを使用し続けます。→リソース消費としては大きい。 • また、TCPとして接続が維持され続けるため、これを逆手にステートフル・セッションリッチなインターフェイスを考えてしまいます。 • が、それではAzureの強みである「スケーラブルなインスタンスの拡張」が出来なくなってしまいます。 • どうやって対処する?
スケーラビリティ1 VIPスワップでは切断されない • インスタンスを入れ替える場合に、VIPスワップを使うと、クライアント側のWebSocket接続(TCP接続)を維持したまま、インスタンスを入れ替える事が出来ます。 VIPスワップ WebSocket接続 (維持される) ここは切断される WebSocketを認識する 負荷分散ルーター DB(データ)
スケーラビリティ1 VIPスワップでは切断されない • クライアント側の接続は維持されますが、サーバー側は当然維持されません。そのため、Azure内のWebSocketが切断され、かつクライアント側は接続が維持されているということを念頭に置く必要があります。 • HTTPによるREST APIの置き換えシナリオであれば、初めからステートレスで設計している筈なので、この挙動に問題なくフィットします。(恐らく、必要なデータはバックエンドのDBに保存している筈) • WebSocketでの接続を念頭に置いていると、便利さゆえに、どこかでステートフルな設計にしてしまう可能性があるので、注意が必要です。
スケーラビリティ2 インスタンス間通信 • 複数のインスタンスが存在すると、インスタンスをまたがってクライアントとのメッセージ送受信を実行する必要があります。 異なるインスタンスに接続している どうやってメッセージを送受信する? DBを経由?
スケーラビリティ2 インスタンス間通信 • SignalRにインスタンス間通信の為の拡張インターフェイスがあります。Azure上では”Azure ServiceBus”が使えます。 Azure ServiceBus
スケーラビリティ2 インスタンス間通信 • Azure ServiceBusは「Microsoft ASP.NET SignalR Service Bus Messaging Backplane」という名称でNuGetで公開されています。“Install-Package Microsoft.AspNet.SignalR.ServiceBus“http://www.asp.net/signalr/overview/signalr-20/performance-and-scaling/scaleout-with-windows-azure-service-bus • ServiceBusの実装は、あまりに多いクライアントにはフィットしないとの話があります。 • 他にも、SQL Serverを使うものや、OSSインメモリデータベースのRedisを使用した実装などがあります。
Cheers! • 本日のスライド・サンプルコードは、後日ブログに掲載します。 • kekyoの丼http://kekyo.wordpress.com