地地地地地地地地 Azure 地地地地 in 地地地 2014.3.1 Kouji Matsui (@kekyo2) SignalR ブブブブブブブ SignalR ブブブブブブブ
Feb 14, 2016
地理冗長の中心で Azure 愛を叫ぶ in 名古屋 2014.3.1 Kouji Matsui (@kekyo2)
SignalR ブートキャンプ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.OwinMicrosoft.Owin.Host.SystemWebASP.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.Core
Microsoft.AspNet.SignalR.SystemWeb
Web.config がおかしい ...
2.0.2 を NuGet で導入時に、 Web.config に不正なエントリーが追加されるので、手動で修正が必要。
アセンブリバージョンの 3番目要素を広くする。この例では「 99」に設定した
OWIN で SignalR のセットアップ
OWIN スタートアップクラスで、 SignalR にコンテキストを転送する
Microsoft.AspNet.SignalR.Core.dllOwin.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”
PlaceLine()
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パケットを確認
Azure Tips
標準的な使用方法は、クラウドサービス( Webロール)ワーカーロールでも使用可能。 OWIN のホストをワーカーロールで実行する
( NuGet で、 OWIN host で検索すると、色々出てきます)。Web サイトでも使用可。但し、 WebSocket で接続する場合は、最大接続数の制限に注意。Free: (5) concurrent connections per website instanceShared: (35) concurrent connections per website instanceStandard: (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 接続)を維持したまま、インスタンスを入れ替える事が出来ます。
WebSocket接続(維持される)VIPスワップここは切断される
WebSocketを認識する負荷分散ルーター DB(データ)
クライアント側の接続は維持されますが、サーバー側は当然維持されません。そのため、 Azure内の WebSocket が切断され、かつクライアント側は接続が維持されているということを念頭に置く必要があります。HTTP による REST API の置き換えシナリオであれば、初めからステートレ
スで設計している筈なので、この挙動に問題なくフィットします。(恐らく、必要なデータはバックエンドの DB に保存している筈)
WebSocket での接続を念頭に置いていると、便利さゆえに、どこかでステートフルな設計にしてしまう可能性があるので、注意が必要です。
スケーラビリティ 1 VIP スワップでは切断されない
複数のインスタンスが存在すると、インスタンスをまたがってクライアントとのメッセージ送受信を実行する必要があります。
スケーラビリティ 2 インスタンス間通信
異なるインスタンスに接続しているどうやってメッセージを送受信する?DBを経由?
SignalR にインスタンス間通信の為の拡張インターフェイスがあります。 Azure 上では” Azure ServiceBus” が使えます。
スケーラビリティ 2 インスタンス間通信
Azure ServiceBus
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 を使用した実装などがあります。
スケーラビリティ 2 インスタンス間通信
Cheers!
本日のスライド・サンプルコードは、後日ブログに掲載します。
kekyo の丼http://kekyo.wordpress.com