nginx met fin à la connexion après 65 000 octets

11

J'ai configuré nginx en tant que frontal pour une application Python exécutée sous gunicorn, mais nginx met fin aux connexions après l'envoi d'environ 65 000 données.

Par exemple, j'ai une vue qui ressemble à ceci:

def debug_big_file(request):
    return HttpResponse("x" * 500000)

Mais lorsque j'accède à cette URL via nginx, je n'obtiens que 65283 octets:

$ curl https://example.com/debug/big-file | wc
…
curl: (18) transfer closed with outstanding read data remaining
   0       1   65283

Notez que tout fonctionne comme prévu lorsque vous accédez directement à gunicorn:

$ curl http://localhost:1234/debug/big-file | wc
…
   0       1   500000

La configuration nginx pertinente:

location / {
    proxy_pass http://localhost:1234/;
    proxy_redirect off;
    proxy_headers_hash_bucket_size 96;
}

Et nginx version 1.7.0

Quelques autres faits:

  • Le nombre d'octets est cohérent d'une demande à l'autre, mais il varie en fonction du contenu (je l'ai d'abord remarqué avec un gros fichier PNG, qui a été coupé après 65 372 octets, pas 65 283)
  • 110 000 octets sont envoyés correctement (c.-à-d. "x" * 110000Renvoie tous les 110 000 octets), mais 120 000 octets ne le sont pas
  • tcpdump suggère que nginx envoie un paquet RST à gunicorn: Nginx envoie la TVD
David Wolever
la source
Il serait utile de voir (a) comment gunicorn choisit d'encadrer des réponses de 110k à 120k octets, et (b) comment nginx choisit ensuite son cadrage pour cette même plage d'échantillons de tailles de charge utile entre 110k et 120k octets. Les trois façons dont HTTP peut encadrer les données: fournir une longueur de contenu; faire un codage en morceaux; ou ne donnez aucun cadre, sauf pour promettre de fermer la prise lorsque le corps sera terminé.
Brandon Rhodes
Un en-tête de longueur de contenu est fourni. Permettez-moi de vider les paquets pour voir ce qui se passe entre les deux autrement…
David Wolever
Hrm, très bizarre. tcpdump suggère que nginx RST active activement la connexion (voir éditer). nginx utilise également HTTP / 1.0 et Connection: close. J'ai également confirmé que l'en- Content-Lengthtête est correct.
David Wolever

Réponses:

10

D'accord! Après avoir vérifié les journaux nginx, cela s'est avéré être le problème:

2014/05/26 16:50:56 [crit] 31396#0: *11 open() "…/proxy_temp/2/00/0000000002" failed (13: Permission denied) while reading upstream, client: 1.2.3.4, server: _, request: "GET /debug/big-file HTTP/1.1", upstream: "http://127.0.0.1:1234/debug/big-file", host: "example.com"

Certains comment les autorisations pour le proxy_temprépertoire ont été gâchées, ce qui a empêché nginx de le mettre correctement en mémoire tampon.

David Wolever
la source
1
Ouais, je viens de résoudre un problème comme celui-ci, j'ai regardé dans les journaux nginx, j'avais une ligne contenant [crit] 6636#0: *16817 open() "/var/lib/nginx/proxy/7/03/0000000037" failed (13: Permission denied) while reading upstream, l'a fait sudo chown -R www-data:www-data /var/lib/nginx/et ça a été corrigé.
Epigene