アプリケーションがGoogle App Engineで10以上の非同期URLフェッチを呼び出すとどうなりますか?
-
30-09-2019 - |
質問
Google Appエンジンを読む ドキュメンテーション 非同期URLフェッチについて:
アプリは、最大10回の同時非同期URLフェッチコールを持つことができます
アプリケーションが一度に10以上の非同期フェッチを呼び出すとどうなりますか?
Google App Engineは例外を提起しますか、それとも単にそれらを提供するのを待っている残りの呼び出しをキューにしますか?
解決
うーん、Swizzecは間違っています。テストするのに十分簡単:
rpc = []
for i in range(1,20):
rpc.append(urlfetch.createrpc())
urlfetch.make_fetch_call(rpc[-1],"http://stackoverflow.com/questions/3639855/what-happens-if-i-call-more-than-10-asynchronous-url-fetch")
for r in rpc:
response = r.get_result().status_code
これは例外を返しません。実際、これはうまく機能します!結果は、請求不可能なアプリケーションで異なる場合があることに注意してください。
Swizecが報告しているのは、アプリケーションへの最大の同時接続に関連する別の問題です。請求可能なアプリの場合、ここには実用的な制限はありませんが、それは単に拡大するだけです(1000MSルールの対象)。
GAEには、リクエストハンドラーがブロッキングURLフェッチを発行することを知る方法がないため、彼が見ている接続500は彼のアプリが実際に行っていることとは関係ありません(平均リクエスト応答時間が> 1000msの場合、それは単純化しすぎるところです。 500の可能性が増加する可能性が高い)。
他のヒント
これは古い質問ですが、受け入れられた答えは間違っているか、時代遅れであり、人々を混乱させる可能性があると思います。私が実際にこれをテストしたのは数ヶ月が経ちましたが、私の経験では、Swizecは、Gaeがリクエストごとに約10の同時の制限の制限を超えるほとんどの非同期URLフェッチを失敗させることは非常に正しいです。
見る https://developers.google.com/appengine/docs/python/urlfetch/#python_making_requests と https://groups.google.com/forum/#!topic/google-appengine/eoytmndvg8u 制限の説明。
デイビッド・アンダーヒルはaを思いつきました PythonのURLフェッチマネージャー, 、アプリケーションコードの制限を超える非同期URLフェッチをキューする。
私はJavaに類似したものを実装しました。これは、(コールバック関数がないため、またはリスブルファットがないため)同期的にブロックします。
/**
* A URLFetchService wrapper that ensures that only 10 simultaneous asynchronous fetch requests are scheduled. If the
* limit is reached, the fetchAsync operations will block until another request completes.
*/
public class BlockingURLFetchService implements URLFetchService {
private final static int MAX_SIMULTANEOUS_ASYNC_REQUESTS = 10;
private final URLFetchService urlFetchService = URLFetchServiceFactory.getURLFetchService();
private final Queue<Future<HTTPResponse>> activeFetches = new LinkedList<>();
@Override
public HTTPResponse fetch(URL url) throws IOException {
return urlFetchService.fetch(url);
}
@Override
public HTTPResponse fetch(HTTPRequest request) throws IOException {
return urlFetchService.fetch(request);
}
@Override
public Future<HTTPResponse> fetchAsync(URL url) {
block();
Future<HTTPResponse> future = urlFetchService.fetchAsync(url);
activeFetches.add(future);
return future;
}
@Override
public Future<HTTPResponse> fetchAsync(HTTPRequest request) {
block();
Future<HTTPResponse> future = urlFetchService.fetchAsync(request);
activeFetches.add(future);
return future;
}
private void block() {
while (activeFetches.size() >= MAX_SIMULTANEOUS_ASYNC_REQUESTS) {
// Max. simultaneous async requests reached; wait for one to complete
Iterator<Future<HTTPResponse>> it = activeFetches.iterator();
while (it.hasNext()) {
if (it.next().isDone()) {
it.remove();
break;
}
}
}
}
}
500エラーが発生し始めます。静かに。
すべてのリクエストの下でログを見るときにのみこれらについて知ります(エラーとしてリストされないでください)。 「リクエストは、同時リクエストの制限に達したため、リクエストが中止された」と言っています。
したがって、非同期の呼び出しがたくさんあるときは、それらのいくつかを吐き出すことができることを確認してください。
これがあなたの質問に答えるかどうかを確認してください:
http://groups.google.com/group/google-appengine/browse_thread/thread/1286139a70ef83c5?fwc=1