SignalR ブートキャンプ - kekyoの丼
Download
Report
Transcript SignalR ブートキャンプ - kekyoの丼
地理冗長の中心でAzure愛を叫ぶ in 名古屋
2014.3.1 Kouji Matsui (@kekyo2)
SignalR ブートキャンプ
自己紹介
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)
Owin
Microsoft.Owin
Microsoft.Owin.Host.SystemWeb
ASP.NETでOWINを動作可能にする
論よりOWIN
「OWINスタートアップクラス」を追加
スタートアップクラスとOwinを結びつける
Hello! OWIN
IOwinContext – HttpContextの抽象インターフェイス
何がどうなってる?
ASP.NETウェブフォームでは、HttpContextを受け取るまでに、
System.Web.UI.Pageからページを生成する必要がありました。
Pageクラスはデカい、ページレンダリングの余分なコードが多い。
シンプルではない。例のように、Hello World的コードであっても、
非常に大がかりな仕掛けが動作します。
OWINは非常にシンプル。IOwinContextを受け取って動作するま
でに必要な、複雑なフレームワーク構造は存在しません。
IOwinContext
OWINでSignalRのセットアップ
NuGetで一発
“Install-Package Microsoft.AspNet.SignalR.SystemWeb” (2.0.2)
Owin
Microsoft.Owin
Microsoft.Owin.Host.SystemWeb
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で表現可能か
どうかは考慮する必要がある。
クライアント側は?
クライアントから、ハブのメソッドを呼び出す
サーバーからのコールバックを受信する
“SharedWhiteBoardHub”
DrawLine()
PlaceLine()
クライアントの実装 (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
パケットを確認
Azure Tips
標準的な使用方法は、クラウドサービス(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/introd
uction-to-websockets-on-windows-azure-web-sites.aspx
WebSocketは高速だけど...
WebSocketはHTTPで接続した際のTCPソケットを使
用し続けます。
→リソース消費としては大きい。
また、TCPとして接続が維持され続けるため、これを
逆手にステートフル・セッションリッチなインター
フェイスを考えてしまいます。
が、それではAzureの強みである「スケーラブルなイ
ンスタンスの拡張」が出来なくなってしまいます。
どうやって対処する?
スケーラビリティ1
VIPスワップでは切断されない
インスタンスを入れ替える場合に、VIPスワップを使うと、クライ
アント側のWebSocket接続(TCP接続)を維持したまま、インス
タンスを入れ替える事が出来ます。
WebSocket接続
(維持される)
WebSocketを認識する
負荷分散ルーター
ここは切断される
VIPスワップ
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/performanceand-scaling/scaleout-with-windows-azure-service-bus
ServiceBusの実装は、あまりに多いクライアントにはフィットしな
いとの話があります。
他にも、SQL Serverを使うものや、OSSインメモリデータベースの
Redisを使用した実装などがあります。
Cheers!
本日のスライド・サンプルコードは、後日
ブログに掲載します。
kekyoの丼
http://kekyo.wordpress.com