11

阅读有关异步 URL 获取的 Google App Engine文档:

该应用最多可以同时进行 10 个异步 URL Fetch 调用

如果应用程序一次调用超过 10 个异步获取会发生什么?
Google App Engine 是否会引发异常或只是将剩余的呼叫排队等待为它们服务?

4

4 回答 4

9

嗯,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 与他的应用程序实际执行的操作无关(顺便说一句,如果您的平均请求响应时间 > 1000 毫秒,您的增加 500 的可能性)。

于 2010-09-05T21:30:40.177 回答
6

这是一个老问题,但我认为接受的答案不正确或过时,可能会使人们感到困惑。我实际上已经测试了几个月,但根据我的经验,Swizec 是非常正确的,GAE 不会排队,而是会失败大多数异步 URL 获取,超过每个请求大约 10 个同时获取的限制。

有关限制的说明,请参阅https://developers.google.com/appengine/docs/python/urlfetch/#Python_Making_requestshttps://groups.google.com/forum/#!topic/google-appengine/EoYTmnDvg8U

David Underhill 提出了一个用于 Python 的 URL Fetch Manager,它将超出应用程序代码限制的异步 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;
                }
            }
        }
    }
}
于 2014-07-04T09:54:24.433 回答
5

500 错误开始发生。默默。

您只有在查看所有请求下的日志时才会发现这些(不要被列为错误)。它只是说“请求被中止,因为您达到了同时请求限制”。

因此,当您进行大量异步调用时,请确保您可以处理其中的一些异常。

于 2010-09-03T22:04:20.920 回答
1

看看这是否回答了你的问题:

http://groups.google.com/group/google-appengine/browse_thread/thread/1286139a70ef83c5?fwc=1

于 2010-10-09T08:40:49.463 回答