Вопрос или проблема
У меня есть приложение на django (основанное на Mezzanine).
Моя конфигурация nginx выглядит так:
upstream myhost {
server 127.0.0.1:8000;
}
server {
listen 80;
server_name www.myhost.ru myhost.ru;
client_max_body_size 10M;
keepalive_timeout 15;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_pass http://myhost;
}
location /static/ {
root /home/myhost/virtualenvs/myhost/project;
access_log off;
log_not_found off;
}
location /robots.txt {
root /home/myhost/virtualenvs/myhost/project/static;
access_log off;
log_not_found off;
}
location /favicon.ico {
root /home/myhost/virtualenvs/myhost/project/static/img;
access_log off;
log_not_found off;
}
}
В браузере я вижу “Внутренняя ошибка сервера”.
Я вижу следующие ошибки в /var/log/nginx/error.log:
2013/04/20 12:24:57 [warn] 11479#0: *1 upstream sent more data than specified in "Content-Length" header while reading upstream, client: 89.189.170.4, server: www.rureads.ru, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8000/", host: "myhost.ru"
2013/04/20 12:38:14 [warn] 11481#0: *19 upstream sent more data than specified in "Content-Length" header while reading upstream, client: 89.189.170.4, server: www.rureads.ru, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:8000/", host: "myhost.ru"
Что может вызвать проблему? Как это исправить?
Измените конфигурацию nginx:
proxy_buffering off;
Хорошо, я долго мучился с этой проблемой. В моем случае у меня была ошибка импорта, связанная с mezzanine, в моем приложении на django (которая не показала себя при использовании сервера разработки django). По какой-то причине (возможно, ошибка gunicorn?), эта ошибка импорта не отображалась в браузере (даже с DEBUG=True) и не регистрировалась gunicorn. Вместо этого я получал только “Внутренняя ошибка сервера” от nginx и сообщение “Upstream sent more data that specified…” в журнале ошибок nginx. Журналы gunicorn просто регистрировали запрос, как будто все прошло хорошо. Поскольку нигде не регистрировалась конкретная ошибка, мне потребовалось много времени, чтобы найти ошибку импорта и исправить ее. В моем случае мне удалось увидеть страницу ошибки django, только закомментировав все MIDDLEWARE_CLASSES в настройках и установив DEBUG=True. Это выявило ошибку импорта, которую я исправил. Затем я повторно включил MIDDLEWARE_CLASSES, перезапустил рабочие процессы gunicorn, и все заработало нормально!
Надеюсь, это сэкономит кому-то время.
Ответ или решение
Ошибка "upstream sent more data than specified in ‘Content-Length’ header while reading upstream" в Nginx может возникать по нескольким причинам, и важно учитывать все аспекты конфигурации вашего веб-приложения, чтобы эффективно диагностировать и устранить эту проблему.
Причины возникновения ошибки
-
Несоответствие заголовка Content-Length:
ЗаголовокContent-Length
указывает длину сообщения, отправляемого клиенту. Если сервер (в вашем случае Django-приложение, работающее на Gunicorn) отправляет больше данных, чем указано в этом заголовке, Nginx выдаст предупреждение, указывая, что происходит несоответствие. -
Ошибка в приложении:
Иногда причиной могут быть ошибки в логике вашего Django-приложения (например, ошибка импорта), которые неявно влияют на длину ответа, или неправильное поведение при обработке данных. Стандартный режим отладки может не всегда показывать все детали ошибки, особенно если вMIDDLEWARE_CLASSES
есть компоненты, которые подавляют обработку. -
Конфигурационные ошибки:
Неправильно настроенные параметры Nginx или часть связки Gunicorn и Nginx могут также приводить к подобным проблемам, если, например, не та версия Python или библиотек используется.
Возможные решения
1. Проверка конфигурации Nginx
Используйте следующий флаг в конфигурации вашего Nginx, чтобы отключить буферизацию. Это поможет, если ошибочный ответ генерируется в процессе передачи данных:
proxy_buffering off;
2. Логирование и диагностирование ошибок
Проверьте логи вашего Django-приложения и Gunicorn:
- Надежно настраивайте уровень логирования, чтобы фиксировать все возможные ошибки. Это поможет выявить потенциальные проблемы.
- Убедитесь, что приложение настроено на отображение полных сообщений об ошибках в режиме отладки.
3. Упрощение настройки MIDDLEWARE_CLASSES
Как оказалось в вашем случае, временное отключение всех MIDDLEWARE_CLASSES
, за исключением необходимых, может быть полезным. Это позволит вам диагностировать, вызывает ли конкретный компонент проблемы.
- Убедитесь, что после выявления и исправления ошибок вы отключаете отладку и снова включаете ваши промежуточные классы.
4. Проверка действий с данными
Если ваше приложение обрабатывает данные, проверьте области, которые могут изменять или не предсказывают длину передаваемых данных (например, сложные сериализаторы или рендереры).
Заключение
Эта ошибка может быть следствием множества факторов, и правильная диагностика включает в себя анализ настроек конфигурации, логов и кодовой базы вашего приложения. Постоянно следите за изменениями в средах разработки и производства, чтобы убедиться в том, что такие ошибки не повторяются. Надеюсь, этот анализ поможет вам более глубоко понять проблему и эффективно ее решить.