Что произойдет, если приложение вызывает более 10 асинхронных URL-запросов в Google App Engine?

Чтение документации Google App Engine по асинхронному URL-адресу Fetch:

Приложение может иметь до 10 одновременных асинхронный выбор URL-запросов

Что произойдет, если приложение вызывает более 10 выборок async за раз?
Создает ли Google App Engine исключение или просто ставит в очередь оставшиеся вызовы, ожидающие их обслуживания?

Ответ 1

Umm, 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 - это другая проблема, связанная с максимальными одновременными подключениями к вашему приложению. Для оплачиваемых приложений здесь нет практического предела, он просто масштабируется (в соответствии с правилом 1000 мс).

GAE не имеет никакого представления о том, что ваш обработчик запроса выдает исправление URL-адреса блокировки, поэтому соединение 500, которое он видит, не связано с тем, что делает его приложение на самом деле (это упрощение btw, если ваше среднее время отклика запроса > 1000 мс, вероятнее всего, 500 увеличений).

Ответ 2

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

Для описания ограничения см. https://developers.google.com/appengine/docs/python/urlfetch/#Python_Making_requests и https://groups.google.com/forum/#!topic/google-appengine/EoYTmnDvg8U.

Дэвид Underhill придумал URL Fetch Manager для Python, который ставит асинхронные URL-адреса, превышающие предел в коде приложения.

Я реализовал нечто подобное для Java, которое синхронно блокирует (из-за отсутствия функции обратного вызова или ListenableFutures) дополнительные запросы:

/**
 * 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;
                }
            }
        }
    }
}

Ответ 3

Началось 500 ошибок. Молча.

Об этом вы узнаете только при просмотре журнала по всем запросам (не указывайте в качестве ошибок). Он просто говорит: "Запрос был прерван, потому что вы достигли предела одновременных запросов".

Итак, когда вы делаете много асинхронных звонков, убедитесь, что вы можете обрабатывать некоторые из них.