Снижение производительности при использовании Nginx в качестве обратного прокси для Sanic + Gunicorn - PullRequest
0 голосов
/ 31 января 2019

Я только начинаю изучать фреймворк Sanic из-за его быстрого теста.Я сделал простой API hello world, затем связал его с Gunicorn.Производительность была довольно хорошей, но когда я скомбинировал ее с Nginx, стало очень плохо.Я обнаружил, что процессы Gunicorn с Nginx были ограничены до 1% - 4% ресурсов процессора для каждого процесса.Без Nginx Gunicorn может достигать 10% для каждого процесса.Я думал, что это из-за неправильной конфигурации Nginx.Кто-нибудь может дать мне несколько советов?

Информация о сервере:

OS: Ubuntu 18.04    
Python version: 3.7.2    
Sanic version: 18.12.0    
Processor: i3-4130

Производительность Sanic + Gunicorn:

wrk -t8 -c1000 -d60s --timeout 2s http://127.0.0.1:8080/
Running 1m test @ http://127.0.0.1:8080/
  8 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    29.54ms   15.13ms 175.77ms   71.23%
    Req/Sec     4.32k     1.29k   19.46k    64.77%
  2060010 requests in 1.00m, 249.50MB read
Requests/sec:  34281.64
Transfer/sec:      4.15MB

Производительность Sanic + Gunicorn + Nginx:

wrk -t8 -c1000 -d60s --timeout 2s http://127.0.0.1:8081/
Running 1m test @ http://127.0.0.1:8081/
  8 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   364.78ms  271.20ms   1.39s    67.53%
    Req/Sec   370.88    251.66     3.52k    87.12%
  177223 requests in 1.00m, 30.42MB read
Requests/sec:   2948.79
Transfer/sec:    518.25KB

Приложение Sanic:

from sanic import Sanic
from sanic.response import json


app = Sanic()
app.config.ACCESS_LOG = False

@app.route("/")
async def test(request):
    return json({"hello": "world"})

Команда Gunicorn:

gunicorn --bind 127.0.0.1:8080 --workers 8 --threads 4 app:app --worker-class sanic.worker.GunicornWorker --name SanicHelloWorld

Глобальная конфигурация Nginx:

worker_processes 8;
worker_rlimit_nofile 400000;
thread_pool sanic_thread_pool threads=32 max_queue=65536;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    multi_accept on;
    worker_connections 25000;
    use epoll;
    accept_mutex off;
}

http {
    access_log off;
    sendfile on;
    sendfile_max_chunk 512k;
    tcp_nopush on;
    tcp_nodelay on;
    server_names_hash_bucket_size 64;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

    upstream sanic-test {
        server 127.0.0.1:8080;
    }
}

Конфигурация Nginx для Sanic + Gunicorn:

server {
    listen 8081;
    listen [::]:8081;

    server_name sanic-test.com www.sanic-test.com;

    location / {
        aio threads=sanic_thread_pool;
        proxy_pass http://127.0.0.1:8080;
    }
}

1 Ответ

0 голосов
/ 05 февраля 2019

Вероятно, это связано с тем, что http://nginx.org/r/proxy_buffering по умолчанию установлен на on, например, когда вы используете http://nginx.org/r/proxy_pass.

Обычно nginx должен контролировать противодавление для вашего бэкэнда, следовательно, буферизация имеет смысл, так как вы не хотите, чтобы ваш реальный бэкэнд подвергался воздействию вектора атаки Slowloris .Аналогично, вы должны выполнять кэширование и ограничивать количество подключений к реальному бэкэнду, который находится за nginx, следовательно, ваш тест, в котором вы устанавливаете все на максимум, но не можете отключить буферизацию, является просто нереальным условием в реальных сценарияхследовательно, вы получаете очень плохие числа в метриках.

Если вы просто хотите увидеть, насколько сильно на производительность влияет простое добавление еще одного слоя в ваш стек HTTP, вы должны установить proxy_buffering off; при использованииproxy_pass.В противном случае тесты должны быть более реалистичными: ваш реальный сервер не должен обрабатывать больше запросов в секунду, чем параметры ввода-вывода устройства хранения, как указано в http://nginx.org/r/proxy_temp_path.

...