Назад | Перейти на главную страницу

Обратный прокси nginx значительно увеличивает задержку в худшем случае

(править: частично понял и работал, см. комментарий)

У меня есть установка с nginx, действующим как обратный прокси-сервер перед сервером приложений CherryPy. Я использую ab для сравнения производительности nginx и not, и замечаю, что в первом случае производительность в худшем случае намного хуже:

$ ab -n 200 -c 10 'http://localhost/noop'
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Finished 200 requests


Server Software:        nginx
Server Hostname:        localhost
Server Port:            80

Document Path:          /noop
Document Length:        0 bytes

Concurrency Level:      10
Time taken for tests:   3.145 seconds
Complete requests:      200
Failed requests:        0
Write errors:           0
Total transferred:      29600 bytes
HTML transferred:       0 bytes
Requests per second:    63.60 [#/sec] (mean)
Time per request:       157.243 [ms] (mean)
Time per request:       15.724 [ms] (mean, across all concurrent requests)
Transfer rate:          9.19 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       1
Processing:     5   48 211.7     31    3007
Waiting:        5   48 211.7     31    3007
Total:          5   48 211.7     31    3007

Percentage of the requests served within a certain time (ms)
  50%     31
  66%     36
  75%     39
  80%     41
  90%     46
  95%     51
  98%     77
  99%    252
 100%   3007 (longest request)
$ ab -n 200 -c 10 'http://localhost:8080/noop'
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Finished 200 requests


Server Software:        CherryPy/3.2.0
Server Hostname:        localhost
Server Port:            8080

Document Path:          /noop
Document Length:        0 bytes

Concurrency Level:      10
Time taken for tests:   0.564 seconds
Complete requests:      200
Failed requests:        0
Write errors:           0
Total transferred:      27600 bytes
HTML transferred:       0 bytes
Requests per second:    354.58 [#/sec] (mean)
Time per request:       28.202 [ms] (mean)
Time per request:       2.820 [ms] (mean, across all concurrent requests)
Transfer rate:          47.79 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.7      0      11
Processing:     6   26  23.5     24     248
Waiting:        3   25  23.6     23     248
Total:          6   26  23.4     24     248

Percentage of the requests served within a certain time (ms)
  50%     24
  66%     27
  75%     29
  80%     31
  90%     34
  95%     40
  98%     51
  99%    234
 100%    248 (longest request)

Что может быть причиной этого? Единственное, о чем я могу думать, это то, что nginx отправляет запросы на бэкэнд в другом порядке, чем они поступали, но это кажется неправдоподобным.

Машина представляет собой экземпляр EC2 c1.medium с 2 ядрами, CherryPy использует пул потоков с 10 потоками, а nginx имеет worker_connections = 1024.

ОБНОВИТЬ: Еще два запутанных вывода:

Худший случай за 3 секунды в вашем первом ab run выглядит как потеря пакета. Вероятно, это результат недостаточного количества настроенных буферов / ресурсов, некоторые возможные причины в произвольном порядке:

  • Слишком маленькая очередь прослушивания на бэкэнде, что приводит к случайным переполнениям очереди прослушивания (Linux обычно настроен на просто отбрасывание пакета SYN в этом случае, что делает его неотличимым от потери пакета; см. netstat -s | grep listen чтобы узнать, не в этом ли проблема).
  • Брандмауэр с полным состоянием на локальном хосте приближается к своему ограничению на количество состояний и из-за этого отбрасывает некоторые случайные SYN-пакеты.
  • В системе отсутствуют сокеты / локальные порты из-за того, что сокеты находятся в состоянии TIME_WAIT, см. этот вопрос если вы используете Linux.

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

С точки зрения nginx любое решение было бы более или менее неправильным (поскольку проблема не в nginx, а скорее в ОС, которая не справляется с нагрузкой и отбрасывает пакеты). Тем не менее, вы можете попробовать несколько уловок, чтобы снизить нагрузку на сетевую подсистему ОС:

  • Настроить соединения keepalive с серверной частью.
  • Настройте бэкэнд для прослушивания сокета домена unix (если ваш бэкэнд его поддерживает) и настройте nginx для прокси-запросов к нему.

NGINX использует HTTP / 1.0 для внутренних соединений и по умолчанию не имеет поддержки активности (см. Ссылку в сообщении Максима для поддержки активности серверной части), поэтому это означает создание нового соединения с сервером для каждого запроса, что несколько увеличивает задержку. Вероятно, у вас также должно быть больше рабочих процессов, 2 * количество ядер ЦП, минимум 5. Если у вас более 10 одновременных запросов, вам может потребоваться больше потоков в CherryPy.