質問
一度にすべてを取得しようとせずに、GWT から JSON オブジェクトのストリームに「サブスクライブ」し、キープアライブ接続で受信イベントをリッスンする方法はありますか?このテクノロジーの最新の流行語は「彗星」だと私は考えています。
キープアライブ接続を開き、受信した株価を含む JSON オブジェクトをそこにリアルタイムで配置する HTTP サービスがあると仮定しましょう。
{"symbol": "AAPL", "bid": "88.84", "ask":"88.86"}
{"symbol": "AAPL", "bid": "88.85", "ask":"88.87"}
{"symbol": "IBM", "bid": "87.48", "ask":"87.49"}
{"symbol": "GOOG", "bid": "305.64", "ask":"305.67"}
...
このイベントをリッスンし、GWT コンポーネント (テーブル、ラベル) をリアルタイムで更新する必要があります。それを行う方法はありますか?
解決
StreamHub用のGWT Cometモジュールがあります:
http://code.google.com/p/gwt-comet-streamhub /
StreamHub は、無料のコミュニティエディションを備えたCometサーバーです。アクションの例がこちらにあります。
StreamHub Cometサーバーをダウンロードして新しいSubscriptionListenerを作成し、StockDemoサンプルを開始点として使用してから、新しいJsonPayloadを作成してデータをストリーミングする必要があります。
Payload payload = new JsonPayload("AAPL");
payload.addField("bid", "88.84");
payload.addField("ask", "88.86");
server.publish("AAPL", payload);
...
GoogleコードサイトからJARをダウンロードし、GWTプロジェクトのクラスパスに追加し、GWTモジュールにインクルードを追加します。
<inherits name="com.google.gwt.json.JSON" />
<inherits name="com.streamhub.StreamHubGWTAdapter" />
GWTコードから接続してサブスクライブします:
StreamHubGWTAdapter streamhub = new StreamHubGWTAdapter();
streamhub.connect("http://localhost:7979/");
StreamHubGWTUpdateListener listener = new StockListener();
streamhub.subscribe("AAPL", listener);
streamhub.subscribe("IBM", listener);
streamhub.subscribe("GOOG", listener);
...
次に、更新リスナー(GWTコードでも)で更新を処理します:
public class StockListener implements StreamHubGWTUpdateListener {
public void onUpdate(String topic, JSONObject update) {
String bid = ((JSONString)update.get("bid")).stringValue();
String ask = ((JSONString)update.get("ask")).stringValue();
String symbol = topic;
...
}
}
streamhub-min.jsをGWTプロジェクトのメインHTMLページに含めることを忘れないでください。
他のヒント
私はいくつかのプロジェクトでこのテクニックを使用しましたが、問題もあります。特に GWT-RPC を通じてのみこれを実行しましたが、原則はデータの処理に使用するメカニズムがどのようなものであっても同じであることに注意してください。正確に何をしているかによっては、物事を過度に複雑にする必要はないかもしれません。
まず、クライアント側では、GWT があらゆる種類のストリーミング データを適切にサポートできるとは思えません。クライアントが実際にデータを処理できるようになる前に、接続を閉じる必要があります。これがサーバー プッシュの観点から意味することは、クライアントはサーバーに接続し、データが利用可能になるまでブロックされ、データが利用可能になった時点でデータが返されるということです。完了した接続で実行されるコードが何であれ、すぐにサーバーとの新しい接続を再度開き、さらなるデータを待つ必要があります。
サーバー側から見ると、新しいデータが利用可能になるまで待機サイクルに入るだけです (ブロックとタイムアウトを備えた Java 同時実行パッケージは特に便利です)。その時点で、サーバーはデータのパッケージをクライアントに返すことができ、クライアントはそれに応じて更新されます。データ フローがどのようなものであるかに応じて考慮すべき事項が数多くありますが、考慮すべき点をいくつか挙げます。
- クライアントがすべての更新を取得することは重要ですか?その場合、サーバーは、クライアントがデータを取得してから再接続するまでの間に、潜在的なイベントをキャッシュする必要があります。
- 大量のアップデートが行われる予定ですか?この場合、クライアントに一度に 1 つの更新を取得させるよりも、多数の更新をパッケージ化し、数秒ごとにチャンクを一度にプッシュダウンする方が賢明である可能性があります。
- サーバーには、クライアント用に大量のキャッシュされたパッケージが蓄積されるのを避けるために、クライアントが離れたかどうかを検出する方法が必要になる可能性があります。
サーバー プッシュのアプローチには 2 つの問題があることがわかりました。クライアントが多数あるということは、Web サーバー上で多数の接続が開かれていることを意味します。問題の Web サーバーによっては、これは多数のスレッドが作成され、開いたままになることを意味する可能性があります。2 つ目は、ドメインあたり 2 リクエストという一般的なブラウザの制限に関係します。画像、CSS、その他の静的コンテンツをセカンド レベル ドメインから提供できる場合は、この問題を軽減できます。
確かにgwtの彗星のようなライブラリがあります- http://code.google.com / p / gwteventservice /
しかし、私は個人的にそれを使用していませんので、本当に良いかどうかを保証することはできませんが、ドコはかなり良いようです。試してみる価値があります。
gwt-rocketの彗星など、私が見たものが他にもいくつかありますライブラリ。
GWTのComet実装の予備的なアイデアは、こちら... にあります。しかし、もっと成熟したものがあるのだろうか。
また、GWT / Comet統合に関するいくつかの洞察は there で利用できます。より最先端のテクノロジー:「Jetty Continuations」。見てみる価値あり。
ここで説明を見つけることができますIBM WebSphere Application Serverでこれを行う方法のソースサンプル)。 Jettyまたは他のComet対応J2EEサーバーとあまり違いはありません。簡単に言うと、JavaオブジェクトをGWT RPCを介してJSON文字列にエンコードし、cometdを使用してクライアントに送信し、そこでDojoが受信し、JSNIコードをトリガーし、ウィジェットメソッドを呼び出し、オブジェクトをデシリアライズします再びGWT RPCを使用します。出来上がり! :)
このセットアップでの私の経験はプラスであり、セキュリティの質問を除いて問題はありませんでした。この場合、彗星にセキュリティを実装する方法は本当に明確ではありません... Comet更新サーブレットは異なるURLを持つ必要があり、J2EEセキュリティを適用できるようです。
JBoss Erraiプロジェクトには、cometdの優れた代替手段を提供する双方向メッセージングを提供するメッセージバスがあります。
ServerPush / CometにAtmosphere Framewrok( http://async-io.org/ )を使用していますGWTアプリケーションで。
クライアント側では、フレームワークにGWT統合があり、これは非常に簡単です。サーバー側では、プレーンなサーブレットを使用します。
現在、本番環境で使用しており、クラスター環境で1000人以上の同時ユーザーがいます。 Atmosphereのソースを変更することで解決する必要がある途中でいくつかの問題が発生しました。また、ドキュメントは本当に薄いです。
フレームワークは無料で使用できます。