2010-09-03 8 views

risposta

9

Umm, Swizzec non è corretto. Semplice da testare:

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 

Questo non restituisce eccezioni. In effetti, funziona perfettamente! Tieni presente che i risultati possono variare in base alle applicazioni non fatturabili.

Ciò che Swizec sta segnalando è un problema diverso, relativo alle connessioni simultanee massime nell'applicazione. Per le app fatturabili non esiste un limite pratico qui btw, ma viene semplicemente ridimensionato (soggetto alla regola dei 1000ms).

GAE non ha modo di sapere che il gestore della richiesta emetterà un recupero URL di blocco, quindi la connessione che sta vedendo non è correlata a ciò che la sua app sta effettivamente facendo (è una semplificazione eccessiva, se il tempo medio di risposta della richiesta è> 1000ms la probabilità di aumenti di 500).

+1

Secondo la mia esperienza, Swizec non ha torto. Vedi la mia risposta qui sotto. –

5

500 errori iniziano a verificarsi. In silenzio.

Si scoprono solo su questi quando si guarda il registro in tutte le richieste (non vengono elencati come errori). Dice semplicemente "La richiesta è stata interrotta perché hai raggiunto il limite di richieste simultanee".

Quindi, quando si effettuano molte chiamate asincrone, assicurarsi di gestire alcune di esse.

+0

Intendiamoci lo stesso accade per qualsiasi e tutte le richieste. Come mangiare attraverso una coda di attività o altro. Apparentemente, se le tue risposte sono molto veloci (credo che sotto i 100ms), Google è disposto a sopportare molto e non farà questo errore. –

+0

uhm .. questo non sta accadendo alla mia applicazione (non vedo 500 errori).Sono in caso di confine con le chiamate 11-13 però. – systempuntoout

6

Questa è una vecchia questione, ma credo che la risposta accettata è errata o non aggiornate e può confondere la gente. Sono passati un paio di mesi da quando ho provato questo, ma nella mia esperienza Swizec ha ragione che GAE non fa la coda ma fallisce la maggior parte degli archivi di URL asincroni che superano il limite di circa 10 simultanei per richiesta.

Vedere https://developers.google.com/appengine/docs/python/urlfetch/#Python_Making_requests e https://groups.google.com/forum/#!topic/google-appengine/EoYTmnDvg8U per una descrizione del limite.

David Underhill ha creato uno URL Fetch Manager for Python, che accoda i recuperi di URL asincroni che superano il limite nel codice dell'applicazione.

ho implementato qualcosa di simile per Java, che in modo sincrono blocchi (a causa della mancanza di una funzione di callback o ListenableFutures) ulteriori richieste:

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