ужасные показатели производительности при одновременных запросах на рельсы 3.0.0 + пассажирский + apache + Ruby 1.9.2 - PullRequest
2 голосов
/ 16 марта 2012

Я использую Rails 3.0.0 + passenger + apache2, работающий на Ruby 1.9.2p290 на экземпляре ec2.

Соответствующие настройки Пассажира (я с ними много не играл):

PassengerMaxPoolSize 30 PassengerPoolIdleTime 0 PassengerMinInstances 10

Кроме того, я подтвердил, что НЕ связан с памятью или процессором ...

Я провел несколько тестов и очень смущен результатами. У меня есть вызов, который делает довольно сложный запрос, который объединяет 5 различных предложений .where (). (Другими словами, он использует AREL совсем немного.)

Когда я запускаю Apache Bench с 1000 вызовами БЕЗ ИСТОРИИ (например, ab -n 1000 -c 1), я получаю следующее:

 Concurrency Level:      1
 Time taken for tests:   222.799 seconds
 Complete requests:      1000
 Failed requests:        0
 Write errors:           0
 Total transferred:      489000 bytes
 HTML transferred:       16000 bytes
 Requests per second:    4.49 [#/sec] (mean)
 Time per request:       222.799 [ms] (mean)
 Time per request:       222.799 [ms] (mean, across all concurrent requests)
 Transfer rate:          2.14 [Kbytes/sec] received

Теперь, когда я запускаю его с параллелизмом, установленным на 10 (например, ab -n 1000 -c 10), я получаю следующее:

 Concurrency Level:      10
 Time taken for tests:   213.957 seconds
 Complete requests:      1000
 Failed requests:        0
 Write errors:           0
 Total transferred:      489001 bytes
 HTML transferred:       16000 bytes
 Requests per second:    4.67 [#/sec] (mean)
 Time per request:       2139.567 [ms] (mean)
 Time per request:       213.957 [ms] (mean, across all concurrent requests)
 Transfer rate:          2.23 [Kbytes/sec] received

Там нет абсолютно никакой пользы от одновременных запросов! Запрос в секунду по-прежнему на уровне ~ 4,5. Как будто сервер обрабатывает запросы последовательно.

Теперь о действительно странной части. Если я посмотрю на выведенный SQL-запрос из интерфейса запросов ActiveRecord и вместо этого просто использую find_by_sql, я получу это без параллелизма:

 Concurrency Level:      1
 Time taken for tests:   49.547 seconds
 Complete requests:      1000
 Failed requests:        0
 Write errors:           0
 Total transferred:      489000 bytes
 HTML transferred:       16000 bytes
 Requests per second:    20.18 [#/sec] (mean)
 Time per request:       49.547 [ms] (mean)
 Time per request:       49.547 [ms] (mean, across all concurrent requests)
 Transfer rate:          9.64 [Kbytes/sec] received

Здесь нет сюрпризов. find_by_sql работает быстрее, чем ActiveRecord и AREL для построения запросов. НО, если я запускаю предыдущий с параллелизмом, установленным в 10, я получаю:

 Concurrency Level:      10
 Time taken for tests:   17.859 seconds
 Complete requests:      1000
 Failed requests:        0
 Write errors:           0
 Total transferred:      489000 bytes
 HTML transferred:       16000 bytes
 Requests per second:    55.99 [#/sec] (mean)
 Time per request:       178.587 [ms] (mean)
 Time per request:       17.859 [ms] (mean, across all concurrent requests)
 Transfer rate:          26.74 [Kbytes/sec] received

Обратите внимание, что количество запросов в секунду увеличивается в 3 раза. Итак, мой вопрос:

Как / Почему использование ActiveRecord (и AREL) для построения запросов приводит к тому, что параллельные запросы так плохо отвечают? Может ли ActiveRecord быть настолько загруженным процессором?

1 Ответ

1 голос
/ 01 апреля 2012

Не видя вашего фактического кода, я бы предположил, что AREL выдает неоптимальный SQL для вашего запроса, что приводит к сбою базы данных.

Сравните оператор SQL, созданный AREL, с вашим собственным SQL. Также попробуйте запустить запрос AREL непосредственно в вашей базе данных, чтобы увидеть, как его производительность сравнивается с вашим SQL. Попробуйте ПОЯСНИТЬ по обоим запросам. Имейте в виду, что некоторые базы данных хуже оптимизируют SQL, поскольку он становится все более сложным.

...