サーバーを頻繁にポーリングする必要のあるアプリケーションを作成する必要がありますが、GAEにはリクエストに制限があるため、大量のリクエストを作成すると非常にコストがかかる可能性があります。長いポーリングを使用して、変更を最大30秒間待機させることは可能ですか?
3 に答える
Google AppEngine には新機能 Channel API があり、優れたリアルタイム アプリケーションを構築できる可能性があります。
もう 1 つの解決策は、mochiweb のようなサード パーティのコメット サーバーを使用するか、iframe パターンでツイストすることです。
クライアント 1、イベントを待機中:
client1 --Iframe Pattern--> Erlang/Mochiweb(HttpLongPolling):
Client2、メッセージを送信:
client2 --XhrIo--> AppEngine --UrlFetch--> Erlang/Mochiweb
コメット パターンで mochiweb を使用するには、Richard Jones が良いトピックを書いています (Google で: Richard Jones A Million-user Comet Application)。
App Engine に Comet のようなロング ポーリング ソリューションを実装しようとしましたが、結果はまちまちでした。
def wait_for_update(request, blob):
"""
Wait for blob update, if wait option specified in query string.
Otherwise, return 304 Not Modified.
"""
wait = request.GET.get('wait', '')
if not wait.isdigit():
return blob
start = time.time()
deadline = start + int(wait)
original_sha1 = blob.sha1
try:
while time.time() < deadline:
# Sleep one or two seconds.
elapsed = time.time() - start
time.sleep(1 if elapsed < 7 else 2)
# Try to read updated blob from memcache.
logging.info("Checking memcache for blob update after %.1fs",
elapsed)
blob = Blob.cache_get_by_key_name(request.key_name)
# Detect changes.
if blob is None or blob.sha1 != original_sha1:
break
except DeadlineExceededError:
logging.info("Caught DeadlineExceededError after %.1fs",
time.time() - start)
return blob
私が見ている問題は、ロング ポーリング リクエストに続くリクエストが、ロング ポーリング リクエストの背後でシリアル化 (同期) されていることです。Chrome でトレースを確認すると、次のようなタイムラインが表示されます。
- リクエスト 1 を送信しました。GET (変更されていない) blob (変更されるまで待機)。
- リクエスト 2 を送信しました。ブロブを変更します。
- 完全なタイムアウトの後、要求 1 が返されます (データは変更されません)。
- リクエスト 2 はサーバーで処理され、成功を返します。
Wireshark と Chrome/timeline を使用して、ロング ポーリングとは別の TCP 接続で変更要求をサーバーに送信していることを確認しました。したがって、この同期化は App Engine 本番サーバーで発生している必要があります。私の知る限り、Google はサーバーの動作に関するこの詳細を文書化していません。
チャネル API を待つことが、App Engine から優れたリアルタイム動作を得るための最善の希望だと思います。
長いポーリングは不可能だと思います。GoogleAppEngineのデフォルトのリクエストタイムアウトは30秒です。長いポーリングでは、メッセージの生成に30秒以上かかると、失敗します。おそらく、短いポーリングを使用したほうがよいでしょう。
もう1つのアプローチは、30秒の制限内で長いポーリングを「シミュレート」することです。メッセージがたとえば20秒以内に到着しない場合にこれを行うために、サーバーは通常のメッセージの代わりに「トークン」メッセージを送信でき、クライアントはそれを消費して再度接続する必要があります。
長いポーリングのためにグーグルアプリエンジンに機能リクエスト(そしてそれが受け入れられた)があるようです