Асинхронный URL-адрес в App Engine

Мое приложение должно выполнять множество операций с хранилищем данных по каждому запросу. Я хотел бы запустить их параллельно, чтобы улучшить время отклика.

Для обновлений хранилища данных я выполняю пакетную установку, поэтому все они происходят асинхронно, что экономит много миллисекунд. App Engine позволяет обновлять до 500 объектов. в параллели.

Но я не нашел встроенной функции, которая позволяла бы выполнять выборки из хранилища данных разных типов параллельно.

Поскольку App Engine позволяет вызовам urlfetch выполняться асинхронно, я создал URL-адрес получателя для каждого типа, который возвращает результаты запроса в виде текста в формате JSON. Теперь мое приложение может выполнять асинхронные вызовы urlfetch для этих URL-адресов, которые могут распараллеливать выборки из хранилища данных.

Этот метод хорошо работает с небольшим количеством параллельных запросов, но App Engine выдает ошибки при попытке выполнить более 5 или 10 таких вызовов urlfetch одновременно.

Я сейчас только тестирую, поэтому каждый urlfetch - это идентичный запрос; поскольку они отлично работают в небольших объемах, но начинают терпеть неудачу при более чем нескольких одновременных запросах, я думаю, что это должно иметь какое-то отношение к вызовам async urlfetch.

Мои вопросы:

  1. Есть ли ограничение на количество вызовов urlfetch.create_rpc (), которые могут выполняться асинхронно?
  2. Синхронная функция urlfecth.fetch () имеет параметр «крайний срок», который позволяет функции ждать ответа до 10 секунд перед ошибкой. Есть ли способ сообщить urlfetch.create_rpc (), как долго ждать ответа?
  3. Что означают ошибки, показанные ниже?
  4. Есть ли лучший способ на стороне сервера для параллельного выполнения различных видов выборки из хранилища данных?

    Файл "/base/python_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", строка 501, в get_result return self .__ get_result_hook (self) File "/ base / python_lib / versions / 1 / google / appengine / api /urlfetch.py ​​", строка 331, в _get_fetch_result raise DownloadError (str (err)) InterruptedError: ('Запрос Wait () был прерван исключением из другого обратного вызова:', DownloadError ('ApplicationError: 5',))


person mb.    schedule 27.12.2009    source источник
comment
Теперь Google решил эту проблему, не требуя сторонних утилит, таких как asynctools. Теперь вы можете выполнять как получение, так и размещение асинхронно. См. Примечания к выпуску SDK версии 1.5.0 здесь: code.google.com/p / googleappengine / wiki / SdkReleaseNotes Добавлена ​​поддержка db.py для асинхронных вызовов хранилища данных. Доступные функции: get_async (), put_async (), delete_async (), allocate_ids_async (). Вызовите get_result для возвращаемого значения асинхронных функций хранилища данных, чтобы заблокировать вызов.   -  person mb.    schedule 06.07.2011


Ответы (3)


Поскольку App Engine разрешает асинхронные вызовы urlfetch, но не позволяет получать асинхронные данные из хранилища данных, я пытался использовать urlfetch RPC для параллельного извлечения из хранилища данных.

Отсутствие асинхронного хранилища данных - общепризнанная проблема:

http://code.google.com/p/googleappengine/issues/detail?id=1889

И теперь есть сторонний инструмент, который позволяет выполнять асинхронные запросы:

http://code.google.com/p/asynctools/

«asynctools - это библиотека, позволяющая выполнять вызовы API Google App Engine параллельно. Вызовы API можно смешивать вместе и ставить в очередь, а затем все запускаются параллельно».

Это именно то, что я искал.

person mb.    schedule 05.02.2010
comment
GAE 1.5+ теперь имеет API асинхронного хранилища данных. - person ; 03.07.2011

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

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

Я бы серьезно подумал о переосмыслении дизайна ваших классов хранилища данных, чтобы уменьшить количество операций чтения и записи, которые должны произойти, поскольку это быстро станет узким местом для вашего приложения.

person Adam Crossland    schedule 27.12.2009
comment
Запись не является проблемой, поскольку App Engine позволяет выполнять асинхронную пакетную запись. Несмотря на то, что индивидуальный пут занимает больше времени, чем отдельный выбор, при параллельном выполнении пут, общее время является приемлемым. Я пытаюсь понять, как выполнять пакетные выборки разных типов параллельно, чтобы сделать то же самое с чтениями. - person mb.; 27.12.2009

Рассматривали ли вы возможность использования TaskQueues для постановки в очередь запросов, которые будут казнен позже?

Если задача возвращает статус 4xx, она будет считаться неудачной и будет повторена позже, чтобы вы могли передать ошибку и обработчик очереди задач повторял бы запросы до тех пор, пока не завершится успешно. Кроме того, поэкспериментировав с размерами сегментов и их скоростью, вы, вероятно, можете заставить очередь задач замедлить запросы настолько, чтобы вы не исчерпали базу данных.

Также есть хорошая оболочка (deferred.defer), которая упрощает работу - вы можете выполнить отложенный вызов (почти) любой функции в вашем приложении.

person James Polley    schedule 30.12.2009
comment
Я не хочу откладывать запросы. Я пытаюсь выполнить несколько операций с хранилищем данных одновременно и вернуть результаты пользователю. App Engine предоставляет пакетные средства для одновременной записи различных типов. Но я не нашел способа выполнять одновременные чтения разных типов. - person mb.; 31.12.2009