web-dev-qa-db-fra.com

La réponse du serveur est interrompue à mi-chemin

J'ai un REST API qui renvoie des réponses json. Parfois (et ce qui semble être complètement aléatoire), la réponse json est coupée à mi-chemin. La chaîne json retournée ressemble donc à:

...route_short_name":"135","route_long_name":"Secte // end of response

Je suis sûr que ce n'est pas un problème d'encodage car le point de coupure continue de changer de position, en fonction de la chaîne json retournée. Je n'ai pas non plus trouvé de taille de réponse particulière pour laquelle la coupure se produit (j'ai vu 65 Ko ne pas être coupé, alors que 40 Ko le feraient).

En regardant l'en-tête de réponse lorsque la coupure se produit:

{
    "Cache-Control" = "must-revalidate, private, max-age=0";
    Connection = "keep-alive";
    "Content-Type" = "application/json; charset=utf-8";
    Date = "Fri, 11 May 2012 19:58:36 GMT";
    Etag = "\"f36e55529c131f9c043b01e965e5f291\"";
    Server = "nginx/1.0.14";
    "Transfer-Encoding" = Identity;
    "X-Rack-Cache" = miss;
    "X-Runtime" = "0.739158";
    "X-UA-Compatible" = "IE=Edge,chrome=1";
}

Ne sonne pas non plus. N'importe qui?

36
samvermette

J'ai eu le même problème:

Nginx a coupé certaines réponses du backend FastCGI. Par exemple, je n'ai pas pu générer une sauvegarde SQL appropriée à partir de PhpMyAdmin. J'ai vérifié les journaux et j'ai trouvé ceci:

2012/10/15 02:28:14 [crit] 16443 # 0: * 14534527 open () "/ usr/local/nginx/fastcgi_temp/4/81/0000004814" a échoué (13: autorisation refusée) lors de la lecture en amont, client : *, serveur:, demande: "POST/ HTTP/1.1", en amont: "fastcgi: //127.0. 0.1: 9000 ", hôte:" ", référent:" http: // */server_export.php? Token = ** "

Tout ce que j'avais à faire pour le réparer était de donner les autorisations appropriées au /usr/local/nginx/fastcgi_temp dossier, ainsi que client_body_temp.

Fixé!

Merci beaucoup samvermette , votre question et réponse m'a mis sur la bonne voie.

34
Clement Nedelcu

J'ai recherché mon nginx error.log fichier et a trouvé ce qui suit:

13870 open() "/var/lib/nginx/tmp/proxy/9/00/0000000009" failed (13: Permission denied) while reading upstream...

On dirait que le proxy de nginx essayait d'enregistrer le contenu de la réponse (transmis par Thin) dans un fichier. Il ne le fait que lorsque la taille de la réponse dépasse proxy_buffers (64 Ko par défaut sur une plate-forme 64 bits). Donc, à la fin, le bogue était connecté à ma taille de réponse à la demande.

J'ai fini de résoudre mon problème en définissant proxy_buffering à off dans mon fichier de configuration nginx, au lieu de mettre à jour proxy_buffers ou correction du problème d'autorisation de fichier.

Je ne sais toujours pas à quoi sert le tampon de nginx. J'apprécierais que quelqu'un puisse ajouter quelque chose à ce sujet. La désactivation de la mise en mémoire tampon est-elle complètement une mauvaise idée?

30
samvermette

J'ai eu un problème similaire avec la coupure de la réponse du serveur.

Cela ne s'est produit que lorsque j'ai ajouté l'en-tête json avant de renvoyer la réponse header('Content-type: application/json');

Dans mon cas, gzip a causé le problème.

Je l'ai résolu en spécifiant gzip_types dans nginx.conf et en ajoutant application/json à lister avant d'activer gzip:

gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/json;
gzip on;
11
Dralac

Merci pour la question et les bonnes réponses, cela m'a fait gagner beaucoup de temps. En fin de compte, la réponse de clement et sam m'a aidé à résoudre mon problème, donc les crédits leur reviennent.

Je voulais juste souligner qu'après avoir lu un peu sur le sujet, il semble qu'il n'est pas recommandé de désactiver proxy_buffering car cela pourrait faire caler votre serveur si les clients (utilisateur de votre système) ont une mauvaise connexion internet par exemple.

J'ai trouvé cette discussion très utile pour mieux comprendre. L'exemple de Francis Daly m'a clairement montré:

Il est peut-être plus facile de considérer le processus complet comme une chaîne de processus.

le navigateur Web parle à nginx, via un lien de 1 Mo/s. nginx parle au serveur en amont, via une liaison de 100 Mo/s. le serveur en amont renvoie 100 Mo de contenu à nginx. nginx renvoie 100 Mo de contenu au navigateur Web.

Lorsque proxy_buffering est activé, nginx peut contenir l'intégralité des 100 Mo, de sorte que la connexion en amont nginx peut être fermée après 1 s, puis nginx peut passer 100 s à envoyer le contenu au navigateur Web.

Lorsque proxy_buffering est désactivé, nginx ne peut prendre le contenu en amont qu'au même rythme que nginx peut l'envoyer au navigateur Web.

Le navigateur Web ne se soucie pas de la différence - il lui faut encore 100 s pour obtenir tout le contenu.

nginx ne se soucie pas beaucoup de la différence - il faut encore 100 s pour envoyer le contenu au navigateur, mais il doit maintenir la connexion ouverte en amont pendant 99 s supplémentaires.

L'amont se soucie de la différence - ce qui aurait pu prendre 1 s prend en fait 100 s; et pour les 99 s supplémentaires, ce serveur en amont ne sert aucune autre demande.

Généralement: le lien nginx-amont est plus rapide que le lien navigateur-nginx; et en amont est plus "lourd" que nginx; il est donc prudent de laisser le traitement en amont terminer le plus rapidement possible.

2
Vlad

Il est possible que vous n'ayez plus d'inodes, ce qui empêche NginX d'utiliser correctement le répertoire fastcgi_temp.

Essayez df -i et si vous avez 0% d'inodes libres, c'est un problème.

Essayez find /tmp -mtime 10 (plus de 10 jours) pour voir ce qui pourrait remplir votre disque.

Ou peut-être que c'est un autre répertoire avec trop de fichiers. Par exemple, accédez à /home/www-data/example.com et comptez les fichiers:

find . -print | wc -l

2
PJ Brunet

Nous avons eu un problème similaire. Cela était dû à l'activation de SO_LINGER sur notre serveur REST (DropWizard). Sous charge, DropWizard déconnectait NGINX avant d'avoir la possibilité de vider ses tampons. Le JSON était> 8 Ko et le frontal recevrait il a tronqué.

1
Chris Kannon

J'ai également eu ce problème - JSON l'analyse du côté client était défectueuse, la réponse était interrompue ou pire encore, la réponse était périmée et a été lue à partir d'un tampon de mémoire aléatoire.

Après avoir parcouru certains guides - Serving Static Content Via POST From Nginx ainsi que Nginx: Fix to "405 Not Allowed" lors de l'utilisation de POST service statique tout en essayant de configurer nginx pour servir un simple fichier JSON.

Dans mon cas, j'ai dû utiliser:

max_ranges 0;

afin que le navigateur n'ait pas d'idées amusantes lorsque nginx ajoute Accept-Ranges: bytes dans l'en-tête de la réponse) ainsi que

sendfile off;

dans mon bloc server pour le proxy qui sert les fichiers statiques. L'ajouter au bloc location qui servirait finalement le fichier JSON trouvé n'a pas aidé.

Un autre protip pour servir les JSONs statiques ne serait pas non plus oublier le type de réponse:

charset_types application/json;
default_type application/json;
charset utf-8;

D'autres recherches ont généré des problèmes d'autorisation de dossier - nginx coupe la fin des pages dynamiques et les met en cache ou des problèmes de mise en mémoire tampon du proxy - Obtention d'une requête fragmentée via nginx , mais ce n'était pas mon cas .

0
Dr1Ku