web-dev-qa-db-fra.com

Chrome se bloque lorsque plusieurs demandes sont adressées à la même ressource?

J'essaie d'implémenter une longue interrogation pour la première fois et j'utilise des objets XMLHttpRequest pour le faire. Jusqu'ici, j'ai réussi à obtenir des événements dans Firefox et Internet Explorer 11, mais Chrome est étrangement l'intrus de cette fois.

Je peux charger une page et tout fonctionne bien. Il fait la demande immédiatement et commence à traiter et à afficher les événements. Si j'ouvre la page dans un deuxième onglet, l'une des pages commence à voir des retards dans la réception des événements. Dans la fenêtre des outils de développement, je vois plusieurs requêtes avec ce type de minutage:

screenshot

"Stalled" durera jusqu'à 20 secondes. Cela ne se produira pas pour chaque demande, mais se produira généralement pour plusieurs demandes consécutives et dans un onglet.

Au début, j’imaginais que c’était un problème avec mon serveur, mais j’ai ensuite ouvert deux onglets IE et deux onglets Firefox. Tous se connectent et reçoivent les mêmes événements sans s’arrêter. Seul Chrome a ce genre de problème.

Je suppose que c'est probablement un problème avec la façon dont je présente ou réponds à la demande. Pour référence, les en-têtes de requête ressemblent à ceci:

Connection: keep-alive
Last-Event-Id: 530
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36
Accept: */*
DNT: 1
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

La réponse ressemble à ceci:

HTTP/1.1 200 OK
Cache-Control: no-cache
Transfer-Encoding: chunked
Content-Type: text/event-stream
Expires: Tue, 16 Dec 2014 21:00:40 GMT
Server: Microsoft-HTTPAPI/2.0
Date: Tue, 16 Dec 2014 21:00:40 GMT
Connection: close

Malgré les en-têtes impliqués, je n'utilise pas EventSource natif du navigateur, mais plutôt un polyfill qui me permet de définir des en-têtes supplémentaires. Le polyfill utilise XMLHttpRequest sous les couvertures, mais il me semble que peu importe la façon dont la demande est faite, elle ne devrait pas rester bloquée pendant 20 secondes.

Qu'est-ce qui pourrait causer le blocage de Chrome comme ceci?

Éditer: Chrome: la page d'événements de net-internals/# de chrome indique qu'il y a une erreur de délai d'attente impliqué:

t=33627 [st=    5]      HTTP_CACHE_ADD_TO_ENTRY  [dt=20001]
                --> net_error = -409 (ERR_CACHE_LOCK_TIMEOUT)

Le message d'erreur fait référence à un correctif ajouté à Chrome il y a six mois ( https://codereview.chromium.org/345643003 ), qui implémente un délai d'attente de 20 secondes lorsque la même ressource est demandée plusieurs fois. En fait, l'un des bogues que le correctif tente de corriger ( le numéro de bogue 46104 ) fait référence à une situation similaire et le correctif a pour but de réduire le temps d'attente.

Il est possible que la solution (ou la solution de contournement) consiste simplement à donner un aspect différent aux demandes, même si Chrome pourrait peut-être respecter l'en-tête "sans cache" défini.

38
fluggo

Oui, ce problème est dû au fait que Chrome a verrouillé le cache et attendu de voir le résultat d'une requête avant de demander à nouveau la même ressource. La solution consiste à trouver un moyen de rendre les demandes uniques. J'ai ajouté un nombre aléatoire à la chaîne de requête et tout fonctionne maintenant.

Pour référence future, il s’agissait de Chrome 39.0.2171.95.

Edit : Depuis cette réponse, je me suis rendu compte que "Cache-Control: no-cache" ne fait pas ce que je pensais. Malgré son nom, les réponses avec cet en-tête peuvent être mises en cache. Je n'ai pas essayé, mais je me demande si l'utilisation de "Cache-Control: no-store", que fait empêcher la mise en cache, résoudrait le problème.

29
fluggo

l'ajout de Cache-Control: no-cache, no-transform a fonctionné pour moi

1
activedecay

J'ai décidé de garder les choses simples et de vérifier les en-têtes de réponse d'un site Web ne présentant pas ce problème et j'ai modifié les en-têtes de réponse pour qu'ils correspondent aux leurs:

Cache-Control: max-age=3, must-revalidate
0
DevDan