Асинхронный URLfetch, когда мы не заботимся о результате? [Python] - PullRequest
6 голосов
/ 23 марта 2011

В каком-то коде, который я пишу для GAE, мне нужно периодически выполнять GET для URL-адреса в другой системе, по сути, «пинговать» его, и меня не очень беспокоит, если запрос завершится неудачно, истечет время ожидания или будет успешным.

Поскольку я в основном хочу «запустить и забыть», а не замедлять собственный код, ожидая запроса, я использую асинхронный urlfetch и не вызываю get_result ().

В моем журнале я получаю предупреждение:

Найдено 1 запросов RPC без соответствующего ответа (предположительно из-за тайм-аутов или других ошибок)

Мне не хватает явно лучшего способа сделать это? Очередь задач или отложенная задача в данном случае кажутся мне излишними.

Любой вклад приветствуется.

Ответы [ 2 ]

6 голосов
/ 24 марта 2011

Задача очереди задач - ваш лучший вариант здесь.Сообщение, которое вы видите в журнале, указывает на то, что запрос ожидает завершения вашего URLFetch, прежде чем вернуться, так что это не поможет.Вы говорите, что задача «перебор», но на самом деле они очень легкие и, безусловно, лучший способ сделать это.Отложенный даже позволит вам просто отложить вызов извлечения напрямую, вместо того, чтобы писать функцию для вызова.

2 голосов
/ 24 марта 2011

Сколько времени занимает завершение async_url_fetch и сколько времени требуется, чтобы предоставить ваш ответ?

Вот возможный подход к использованию API в Python.

Некоторые моменты для рассмотрения.

  • Многие веб-серверы и обратные прокси-серверы не отменяют запрос после его запуска. Поэтому, если на вашем удаленном сервере вы пингуете запрос на передачу запроса, но занимает много времени для его обслуживания, используйте крайний срок для вашего create_rpc (deadline = X), чтобы X возвращался из-за истечения времени ожидания. Пинг все еще может быть успешным. Этот метод работает и против самого appengine.

  • GAE RPC

    • RPC после настройки через make_call / make_fetch_call на самом деле отправляются только после ожидания одного из них.
    • Также любой только что завершившийся rpc будет вызываться с помощью обратного вызова, когда завершится текущий ожидаемый вызов.
    • Вы можете создать async_urlfetch rpc и поставить его в очередь, используя make_fetch_call, как можно раньше при обработке вашего запроса, пока не ждите его.
    • Выполните работу по обслуживанию страницы, например, вызовы memcache / datastore, чтобы начать работу. Первый вызов одного из них выполнит ожидание, которое отправит ваш async_urlfetch.
    • Если urlfetch завершается во время этого другого действия, будет вызван обратный вызов в urlfetch, что позволит вам обработать результат.
    • Если вы вызовете get_result (), он заблокирует функцию wait () до истечения срока или вернется, если результат не будет готов.

Напомним.

Подготовьте долгосрочный url_fetch с разумным сроком и обратным вызовом. Поставьте в очередь это используя make_fetch_call. Сделайте работу, которую вы хотели для страницы. Верните страницу независимо от того, завершен или завершен url_fetch, и не дожидаясь его.

Базовый уровень RPC в GAE является асинхронным, кажется, есть более изощренный способ выбрать то, что вы хотите ждать в работе.

В этих примерах используется 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

Отображение с использованием RPC-команды memcache для запуска работы.

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 Prod Log:

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)

Асинхронное извлечение URL отправляется, когда memcache.get вызывает wait ()

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
...