みなさん、こんにちは。 ストリーミング API ってご存知ですか?
実際のプロジェクトで利用していますか??
今回は、Salesforce 上でプッシュ通知を実現するストリーミング API について、背景となる技術の解説と動作概要、簡単なサンプルコードを利用して解説します。 また、制限事項も併せて紹介しますので、実際のプロジェクトにおいて利用を検討する場合の参考にして頂ければと思います。
結構簡単に使えますよ!
ストリーミングAPI とは?
一言でいえば、SOQL クエリで定義した条件に基づいて、Salesforce データの変更監視を行い、条件にヒットした場合に、通知を待っている( Subscribe (購読) と言います)クライアントに対してプッシュ通知を 一斉配信する仕組みです。
Summer '12 以降では、API が有効であればどの組織でも利用可能ですので、Developer Edition?組織で気軽に試してみることができます。
また、プッシュ通知は Salesforce アプリケーション内のページ、Salesforce 外のサーバやページ、Java クライアントから受信可能です 。
今回のサンプルは、Visualforce ページで受信を行います。
そもそも プッシュ通知とは?
サーバで発生したイベントをきっかけに、クライントからの要求なしに情報を送信することができる技術です。
従来のクライアントからの要求に応じて情報を送信するプル方式では、ユーザが明示的にページをリフレッシュするか、ページ遷移を行わない限り表示されているページは更新されません。 そのため、サーバでイベントが発生したことをクライアントが知るためには、定期的にページ要求を送信して結果を受け取る(ポーリング)必要があります。
サーバ側ではポーリングのたびに HTTP コネクションの生成・情報送信・コネクションを閉じる という一連の処理を行う必要があるため、多数のクライアントからポーリングが行われると、多大なサーバリソース・ネットワーク帯域を消費することになってしまいます。
クライントの要求をページの一部のみに限定して非同期にリクエストを行う Ajax を利用すると、ネットワーク帯域消費は抑えることができますが、サーバ側イベントの有無に関係なく定期的に受信するページ要求に対応する必要があるため、効率的とは言えません。
特に Salesforce の場合には、外部から SOAP/REST API 等でポーリングを行うと API 要求数を消費することになるため、頻繁なポーリングは行うべきではありません。
そこで登場したのが、ストリーミング API です。
どのような技術で実現されている?
ストリーミング API は、HTTPでの非同期メッセージ提供を目的として設計された?Bayeux(バイユー) プロトコルを実装する、CometD フレームワークで実現されています。 これは Long polling と呼ばれる技術を利用して、擬似的にサーバからクライアントへの情報プッシュを行う方式です。
Long pollling の具体的な動作としては
- クライアントからは従来のポーリング同様に、サーバに対して要求を発行
- サーバ側はその要求に対して即時に応答を返さず、ずっと掴んだままにしておく
- サーバ側でイベントの発生を検知したら、それまで掴みっぱなしになっていた複数の要求に対して一斉に応答を返す
- 応答を受信したブラウザはすぐに次の要求を再発行して、ふたたび応答待ちの状態へと戻る
⇒ 結果的にサーバからのプッシュ通知が行われたような動作になります。
ストリーミング API の設定・動作概要
それでは、ストリーミング API を利用する場合の設定と動作を簡単に見てみましょう。
サーバ側の設定
PushTopic を定義する
具体的には、標準オブジェクトである「PushTopic」オブジェクトにレコードを作成します。 PushTopic レコードには SOQL で監視条件(PushTopic クエリ)を設定し、名前(PushTopic チャネル)を定義します。 これだけでサーバ側の準備は完了です。
クライアントからの受信処理
PushTopic チャネルに接続する(Subscribe)
http://cometd.org/ でダウンロード可能な JavaScript または Java ?ライブラリを利用して、PushTopic チャネルへの接続を行います。なお、1つのクライアントから複数の PushTopic チャネルへの同時 Subscribe が可能です。
サーバからの通知配信
PushTopic クエリの条件評価にマッチした場合は Subscribe 中のクライアントに一斉通知配信
PushTopic クエリが参照しているオブジェクトのレコード作成・更新ごとに、条件評価が行われます。 なお、ストリーミング API ではこの通知イベント発生数が Unlimited Edition および?Enterprise Edition 組織の場合は 24 時間で 20,000 件という制限となっており、従来の API 要求数の制限とは別に管理されています。(従来の API 要求数同様、組織情報から参照可能です)
サンプル設定およびコード
前置きが長くなりましたが、いよいよ実際に設定・開発を行い、動作を見てみましょう。
想定シナリオ
ある ERP システムを利用するユーザ企業を想定します。 営業担当者が受注データを登録しますが、在庫の引当が出来なかった場合には、機会損失を防ぐために、ほぼリアルタイムで在庫・調達管理担当者に知らせる必要があります。 メールによる通知を利用すると見逃す可能性があるため、在庫・調達管理担当者が通常見ている在庫参照画面に通知を表示したいという要望を受けました。
1. PushTopic レコードの作成
まずは PushTopic レコードを作成します。レコードを作成する手段は特に問いません。
- レコード作成時の必須項目は Name(PushTopic チャネル)、 Query(PushTopic クエリ)、 ApiVersion です。
- このサンプルの場合、レコードが作成・更新時に評価を行い(NotifyForOperations: All)、新規作成時と SELECT 句 または WHERE 句で参照している項目に更新があり(NotifyForFields: Referenced)、なおかつ WHERE 句の条件に一致する場合を対象とします。
※注意事項
- SELECT 句には必ず Id を含めること
- 1つのクエリにつき参照可能なエンティティは1つのみであり、リレーションクエリは利用できない
- 集計クエリ、COUNT、LIMIT、ORDER BY、GROUP BY、NOT(NOT INは可)、OFFSET、TYPEOF は利用できない。また、数式項目はSELECT 句で指定は可能だが、WHERE 句では指定できない
- 接続中の CometD セッションが存在する場合は、クエリの変更はできない Subscribe 中のページ等を閉じてから、110秒後にソケットタイムアウトとなり編集可能になる
2. CometD で利用する JavaScript ファイルを静的リソースに登録する
CometD の JavaScript ライブラリ をダウンロードして以下の JavaScript ファイルを抽出し、静的リソースに適切な名前で登録します。
- cometd-2.2.0/cometd-javascript/common/target/org/cometd.js
- cometd-2.2.0/cometd-javascript/jquery/src/main/webapp/jquery/jquery-1.5.1.js
- cometd-2.2.0/cometd-javascript/jquery/src/main/webapp/jquery/json2.js
- cometd-2.2.0/cometd-javascript/jquery/src/main/webapp/jquery/jquery.cometd.js
3. Visualforce ページを作成する
商品在庫オブジェクト(gii__ProductInventory__c) のリストビューを表示するシンプルなページに、通知結果を表示する Visualforce ページです。
2~5行目:CometD の JavaScript ライブラリを include しています
※今回は分かり易さのために個々に Include していますが、本来は zip 形式でまとめて静的リソースに登録し、include することをお勧めします。
12~15行目: エンドポイントに接続
19行目:PushTopic チャネルに Subscribe を行い、コールバックを仕掛けます
20~30行目:通知を受信した場合の表示処理です
4. 動作確認
受注残が発生すると、数秒後に通知が表示されました! これを Visualforce ページのみならず、Visualforce コンポーネントに実装してアプリケーション内の Visualforce ページで共通的に利用すれば、アプリケーション全体で統一的に通知を表示することも可能ですね。
利用上の注意点など
- 完全なリアルタイム通知ではない(3秒間隔でサーバ側イベント確認実施)
- 通知の永続性と信頼性は保証しない 例えば、システムの使用負荷が高い場合や、クライアントからの処理タイミングによりメッセージを受信しない可能性がある
- 通知を受け取るユーザアカウントに PushTopic 標準オブジェクトと、PushTopic クエリが参照するオブジェクトおよび項目に対する「参照」権限が必要
- Bulk API によって生成されたイベントは、通知は行われない(通知の量が許容量を超える可能性があるため)
- 対応ブラウザは Internet Explorer 8 以上 または Firefox 4 以上※本サンプルは Chrome 26.0.1410.64 で動作確認済
ストリーミング API の制限
最後に、ストリーミング API の制限を紹介します。 ※リリースごとに緩和されていますので、最新状況はこちらでご確認ください
説明 | 制限 |
組織あたりのトピック (PushTopic レコード) の最大数 | 20 |
トピックあたりのクライアント (登録者) の最大数 | Unlimited Edition および Enterprise Edition 組織の場合は20、他のすべての組織の場合は 10 |
全トピックの同時クライアント (登録者) の最大数 | Unlimited Edition および Enterprise Edition 組織の場合は20、他のすべての組織の場合は 10 |
1 日あたりのイベントの最大数 (24 時間) | Unlimited Edition および Enterprise Edition 組織の場合は20,000、他のすべての組織の場合は10,000 (ただし、無料の組織の場合の最大数は 1,000) |
接続中のソケットタイムアウト (CometD セッション) | 110 秒 |
接続成功後の再接続までのタイムアウト (keepalive) | 40 秒 |
CometD セッションの最大有効期間 (アクティビティの有無にかかわらず) | 2 時間 |
PushTopic レコードのQuery 項目でのSOQL クエリの最大長 | 1300 文字 |
PushTopic 名の最大 | 25 文字 |
制限の中でも「トピックあたりのクライアント (登録者) の最大数」と「全トピックの同時クライアント (登録者) の最大数」は厳しい制限ですので、実際に利用する際は十分に検討してください。 なお、どうしても増やす必要がある場合には、salesforce.com に問い合わせると制限を拡張できるかもしれません。
まとめ
現状では厳しい制限もあり、用途を慎重に選ぶ必要のある技術ですが、大変簡単に利用することができることはご理解頂けたのではないかと思います。 現在ポーリングのようなことを行っている場合や、データの変更を一斉に通知したい場合などは、是非一度検討してみて下さい。