6

在我为 GAE 编写的一些代码中,我需要定期对另一个系统上的 URL 执行 GET,本质上是“ping”它,如果请求失败、超时或成功,我并不十分担心。

因为我基本上想“触发并忘记”而不是通过等待请求来减慢我自己的代码,所以我使用的是异步 urlfetch,而不是调用 get_result()。

在我的日志中,我收到一条警告:

发现 1 个没有匹配响应的 RPC 请求(可能是由于超时或其他错误)

我是否错过了一个明显更好的方法来做到这一点?在这种情况下,任务队列或延迟任务似乎(对我来说)有点过头了。

任何输入将不胜感激。

4

2 回答 2

7

任务队列任务是您最好的选择。您在日志中看到的消息表明该请求正在等待您的 URLFetch 在返回之前完成,因此这无济于事。你说一个任务是“矫枉过正”,但实际上,它们非常轻量级,而且绝对是做到这一点的最佳方式。Deferred 甚至允许您直接推迟 fetch 调用,而不必编写函数来调用。

于 2011-03-23T22:55:09.950 回答
2

async_url_fetch 需要多长时间才能完成以及提供您的响应需要多长时间?

这是一种可能的方法来利用 api 在 python 中的工作方式。

需要考虑的几点。

  • 许多网络服务器和反向代理一旦启动就不会取消请求。因此,如果您正在 ping 的远程服务器提示请求但需要很长时间才能为其提供服务,请在您的 create_rpc(deadline=X) 上使用截止日期,以便 X 由于超时而返回。ping 可能仍会成功。这种技术也适用于 appengine 本身。

  • GAE RPC

    • 通过 make_call/make_fetch_call 提示后的 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 到同一应用程序的第二个实例。

wait() 调度 rpc 工作的示例:

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 回答