6

私が GAE 用に書いているいくつかのコードでは、別のシステムの URL で定期的に GET を実行する必要があります。つまり、本質的に「ping」を実行する必要があり、要求が失敗したり、タイムアウトしたり、成功したりするかどうかはあまり心配していません。

私は基本的に「起動して忘れる」必要があり、リクエストを待って自分のコードを遅くしたくないので、get_result() を呼び出さずに非同期の urlfetch を使用しています。

ログに次の警告が表示されます。

一致する応答のない 1 つの RPC 要求が見つかりました (おそらくタイムアウトまたはその他のエラーが原因です)

これを行うための明らかに良い方法がありませんか?この場合、Task Queue または Deferred Task は (私には) やり過ぎのように思えます。

任意の入力をいただければ幸いです。

4

2 に答える 2

7

ここでは、タスク キュー タスクが最適なオプションです。ログに表示されているメッセージは、リクエストが戻る前に URLFetch の完了を待っていることを示しているため、これは役に立ちません。タスクは「やり過ぎ」だと言いますが、実際には、タスクは非常に軽量であり、間違いなくこれを行うための最良の方法です。Deferred を使用すると、呼び出す関数を記述する必要がなく、フェッチ呼び出しを直接遅延することもできます。

于 2011-03-23T22:55:09.950 に答える
2

async_url_fetch が完了するまでにどのくらいの時間がかかり、応答を提供するのにどのくらいの時間がかかりますか?

Python で API が機能する方法を活用するための可能なアプローチを次に示します。

考慮すべきいくつかの点。

  • 多くの Web サーバーとリバース プロキシは、開始された要求をキャンセルしません。そのため、ping を実行しているリモート サーバーが要求を通知するが、処理に時間がかかる場合は、create_rpc(deadline=X) で期限を設定して、タイムアウトにより X が返されるようにします。ping は引き続き成功する可能性があります。この手法は、appengine 自体に対しても機能します。

  • GAE RPC

    • make_call/make_fetch_call を介してキューに入れられた後の RPC は、実際には、そのうちの 1 つが待機された後にのみディスパッチされます。
    • また、現在待機中の rpc が終了すると、終了したばかりの rpc のコールバックが呼び出されます。
    • async_urlfetch rpc を作成し、リクエストを処理するできるだけ早い段階で make_fetch_call を使用してキューに入れることができます。まだ待たないでください。
    • 作業を進めるための memcache/datastore 呼び出しなど、実際のページ サービング作業を行います。これのいずれかへの最初の呼び出しは、async_urlfetch をディスパッチする待機を実行します。
    • この他のアクティビティ中に urlfetch が完了すると、urlfetch のコールバックが呼び出され、結果を処理できるようになります。
    • get_result() を呼び出すと、締め切りまで wait() でブロックされるか、結果が準備できていない限り返されます。

要点をまとめると。

合理的な期限とコールバックを使用して、長時間実行される url_fetch を準備します。make_fetch_call を使用してキューに入れます。ページに必要な作業を行います。url_fetch が完了したか締め切られたかに関係なく、それを待たずにページを返します。

GAE の基盤となる RPC レイヤーはすべて非同期です。作業中に何を待ちたいかを選択するためのより洗練された方法があるようです。

これらの例では、sleep と url_fetch を同じアプリの 2 番目のインスタンスに使用しています。

rpc 作業をディスパッチする wait() の例:

class AsyncHandler(RequestHandler):

    def get(self, sleepy=0.0):
        _log.info("create rpc")
        rpc = create_rpc()
        _log.info("make fetch call")
        # url will generate a 404
        make_fetch_call(rpc, url="http://<my_app>.appspot.com/hereiam")
        _log.info("sleep for %r", sleepy)
        sleep(sleepy)
        _log.info("wait")
        rpc.wait()
        _log.info("get_result")
        rpc.get_result()
        _log.info("return")
        return "<BODY><H1>Holla %r</H1></BODY>" % sleepy

4秒間スリープした後に呼び出される待機は、のディスパッチを示します

2011-03-23 17:08:35.673 /delay/4.0 200 4093ms 23cpu_ms 0kb Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16,gzip(gfe)
I 2011-03-23 17:08:31.583 create rpc
I 2011-03-23 17:08:31.583 make fetch call
I 2011-03-23 17:08:31.585 sleep for 4.0
I 2011-03-23 17:08:35.585 wait
I 2011-03-23 17:08:35.663 get_result
I 2011-03-23 17:08:35.663 return
I 2011-03-23 17:08:35.669 Saved; key: __appstats__:011500, part: 48 bytes, full: 4351 bytes, overhead: 0.000 + 0.006; link: http://<myapp>.appspot.com/_ah/stats/details?tim
2011-03-23 17:08:35.636 /hereiam 404 9ms 0cpu_ms 0kb AppEngine-Google; (+http://code.google.com/appengine; appid: s~<myapp>),gzip(gfe)

非同期ディスパッチされた呼び出し。

E 2011-03-23 17:08:35.632 404: Not Found Traceback (most recent call last): File "distlib/tipfy/__init__.py", line 430, in wsgi_app rv = self.dispatch(request) File "di
I 2011-03-23 17:08:35.634 Saved; key: __appstats__:015600, part: 27 bytes, full: 836 bytes, overhead: 0.000 + 0.002; link: http://<myapp>.appspot.com/_ah/stats/details?time

memcache RPC の待機を使用して作業を開始することを示しています。

class AsyncHandler(RequestHandler):

    def get(self, sleepy=0.0):
        _log.info("create rpc")
        rpc = create_rpc()
        _log.info("make fetch call")
        make_fetch_call(rpc, url="http://<myapp>.appspot.com/hereiam")
        _log.info("sleep for %r", sleepy)
        sleep(sleepy)
        _log.info("memcache's wait")
        memcache.get('foo')
        _log.info("sleep again")
        sleep(sleepy)
        _log.info("return")
        return "<BODY><H1>Holla %r</H1></BODY>" % sleepy

Appengine 製品ログ:

2011-03-23 17:27:47.389 /delay/2.0 200 4018ms 23cpu_ms 0kb Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16,gzip(gfe)
I 2011-03-23 17:27:43.374 create rpc
I 2011-03-23 17:27:43.375 make fetch call
I 2011-03-23 17:27:43.377 sleep for 2.0
I 2011-03-23 17:27:45.378 memcache's wait
I 2011-03-23 17:27:45.382 sleep again
I 2011-03-23 17:27:47.382 return
W 2011-03-23 17:27:47.383 Found 1 RPC request(s) without matching response (presumably due to timeouts or other errors)
I 2011-03-23 17:27:47.386 Saved; key: __appstats__:063300, part: 66 bytes, full: 6869 bytes, overhead: 0.000 + 0.003; link: http://<myapp>.appspot.com/_ah/stats/details?tim
2011-03-23 17:27:45.452 /hereiam 404 10ms 0cpu_ms 0kb AppEngine-Google; (+http://code.google.com/appengine; appid: s~<myapp>),gzip(gfe)

memcache.get が wait() を呼び出すときに非同期 URL フェッチがディスパッチされる

E 2011-03-23 17:27:45.446 404: Not Found Traceback (most recent call last): File "distlib/tipfy/__init__.py", line 430, in wsgi_app rv = self.dispatch(request) File "di
I 2011-03-23 17:27:45.449 Saved; key: __appstats__:065400, part: 27 bytes, full: 835 bytes, overhead: 0.000 + 0.002; link: http://<myapp>.appspot.com/_ah/stats/details?time
于 2011-03-23T23:07:46.280 に答える