2013-12-09 3 views
4

Я запускаю очень простой RESTful API на AWS, используя Node.js. API принимает запрос в виде «/ отдых/пользователей/JDoe» и возвращает следующее (это не все сделано в памяти, не баз данных, участвующих):Медленная производительность для Node.js, работающая на AWS

{ 
    username: 'jdoe', 
    firstName: 'John', 
    lastName: 'Doe' 
} 

производительность этого API на Node.js + AWS ужасен по сравнению с локальной сетью - всего 9 запросов/сек против 2214 запросов в секунду в локальной сети. AWS запускает экземпляр m1.medium, тогда как локальный Node-сервер - настольный компьютер с процессором Intel i7-950. Попытка выяснить, почему такая огромная разница в производительности.

контрольные показатели с помощью Apache Bench заключаются в следующем:

Локальная сеть

10000 запросов с параллелизмом 100/группы

> ab -n 10000 -c 100 http://192.168.1.100:8080/rest/users/jdoe 

Document Path:   /rest/users/jdoe 
Document Length:  70 bytes 

Concurrency Level:  100 
Time taken for tests: 4.516 seconds 
Complete requests:  10000 
Failed requests:  0 
Write errors:   0 
Total transferred:  2350000 bytes 
HTML transferred:  700000 bytes 
Requests per second: 2214.22 [#/sec] (mean) 
Time per request:  45.163 [ms] (mean) 
Time per request:  0.452 [ms] (mean, across all concurrent requests) 
Transfer rate:   508.15 [Kbytes/sec] received 

Connection Times (ms) 
       min mean[+/-sd] median max 
Connect:  0 0 0.4  0  2 
Processing: 28 45 7.2  44  74 
Waiting:  22 43 7.5  42  74 
Total:   28 45 7.2  44  74 

Percentage of the requests served within a certain time (ms) 
    50%  44 
    66%  46 
    75%  49 
    80%  51 
    90%  54 
    95%  59 
    98%  65 
    99%  67 
100%  74 (longest request) 

AWS

1000 запросов с параллельности от 100/группа (10000 запросов заняло бы слишком много времени)

C:\apps\apache-2.2.21\bin>ab -n 1000 -c 100 http://54.200.x.xxx:8080/rest/users/jdoe 
Document Path:   /rest/users/jdoe 
Document Length:  70 bytes 

Concurrency Level:  100 
Time taken for tests: 105.693 seconds 
Complete requests:  1000 
Failed requests:  0 
Write errors:   0 
Total transferred:  235000 bytes 
HTML transferred:  70000 bytes 
Requests per second: 9.46 [#/sec] (mean) 
Time per request:  10569.305 [ms] (mean) 
Time per request:  105.693 [ms] (mean, across all concurrent requests) 
Transfer rate:   2.17 [Kbytes/sec] received 

Connection Times (ms) 
       min mean[+/-sd] median max 
Connect:  98 105 3.8 106  122 
Processing: 103 9934 1844.8 10434 10633 
Waiting:  103 5252 3026.5 5253 10606 
Total:  204 10040 1844.9 10540 10736 

Percentage of the requests served within a certain time (ms) 
    50% 10540 
    66% 10564 
    75% 10588 
    80% 10596 
    90% 10659 
    95% 10691 
    98% 10710 
    99% 10726 
100% 10736 (longest request) 

Вопросы:

  • Connect время AWS 105 мс (средн) по сравнению с 0 мс в локальной сети. Я предполагаю, что это связано с тем, что для открытия сокета AWS на сервер в локальной сети требуется намного больше времени. Есть ли что-то, что можно сделать здесь для повышения производительности при загрузке, если запросы поступают с нескольких компьютеров по всему миру.
  • Более серьезное время обработки сервера - 45 мс для локального сервера по сравнению с 9,9 секундами для AWS! Я не могу понять, что здесь происходит. Сервер только нажимает 9.46 запросов/сек. который является арахисом!

Любое понимание этих вопросов очень ценится. Я нервничаю из-за серьезного применения на Node + AWS, если он не может выполнить супер быстро на таком простом приложении.

Для справки вот мой код сервера:

var express = require('express'); 

var app = express(); 

app.get('/rest/users/:id', function(req, res) { 
    var user = { 
     username: req.params.id, 
     firstName: 'John', 
     lastName: 'Doe' 
    }; 
    res.json(user); 
}); 

app.listen(8080); 
console.log('Listening on port 8080'); 

Редактировать

Single запрос, отправленный в изоляции (-n 1 -с 1)

Requests per second: 4.67 [#/sec] (mean) 
Time per request:  214.013 [ms] (mean) 
Time per request:  214.013 [ms] (mean, across all concurrent requests) 
Transfer rate:   1.07 [Kbytes/sec] received 

Connection Times (ms) 
       min mean[+/-sd] median max 
Connect:  104 104 0.0 104  104 
Processing: 110 110 0.0 110  110 
Waiting:  110 110 0.0 110  110 
Total:  214 214 0.0 214  214 

10 запрос все отправленные одновременно (-n 10 -c 10)

Requests per second: 8.81 [#/sec] (mean) 
Time per request:  1135.066 [ms] (mean) 
Time per request:  113.507 [ms] (mean, across all concurrent requests) 
Transfer rate:   2.02 [Kbytes/sec] received 

Connection Times (ms) 
       min mean[+/-sd] median max 
Connect:  98 103 3.4 102  110 
Processing: 102 477 296.0 520  928 
Waiting:  102 477 295.9 520  928 
Total:  205 580 295.6 621 1033 

Результаты использования Wrk

Как полагает Андрей Сидоров.Результаты гораздо лучше - 2821 запросов в секунду:

Running 30s test @ http://54.200.x.xxx:8080/rest/users/jdoe 
    12 threads and 400 connections 
    Thread Stats Avg  Stdev  Max +/- Stdev 
    Latency 137.04ms 48.12ms 2.66s 98.89% 
    Req/Sec 238.11  27.97 303.00  88.91% 
    84659 requests in 30.01s, 19.38MB read 
    Socket errors: connect 0, read 0, write 0, timeout 53 
Requests/sec: 2821.41 
Transfer/sec: 661.27KB 

Так что, конечно, выглядит как преступник ApacheBench! Невероятно!

+0

Рассекая это на более мелкие куски, то первый вопрос, который выскакивает есть то, что делает один запрос, отправленный в изоляции выглядеть так далеко, как время отклика? Это разумно? Во-вторых, во время бенчмаркинга вы максимизируете CPU на машине AWS? Существует ли нижняя точка останова параллелизма, где уровни отклика? –

+0

Я добавил числа для одного запроса и 10 одновременных запросов (см. Правки в вопросе). Время отклика все еще довольно велико: 214 мс и 580 мс (4,67 запросов/сек и 8,81 запросов/сек). CPU на AWS практически бездействует (1,25%). – Naresh

+0

Вы хотите провести тесты в рамках AWS, чтобы получить лучший ответ от яблок к яблокам, потому что я подтвердил то, что я подозревал (в моих собственных тестах), что «connect» никогда не может быть меньше приблизительного времени пинга от ' ab 'на сервер, а «total» никогда не может быть меньше 2 x ping ... это синхронизация * всего * соединения от открытого до закрытого; поэтому, хотя у вас действительно есть что-то стоящее, чтобы расследовать, я подозреваю, что вы не увидите числа, которые особенно значимы или действительно сопоставимы с местным тестом, пока вы не попробуете «локальный» тест, инициированный в той же зоне доступности EC2. –

ответ

7

Это, вероятно, проблема с проблемой (см. Также this question). В коде сервера нет ничего плохого. Я предлагаю попробовать измерить с помощью инструмента тестирования нагрузки wrk. Ваш пример на моем t1.micro:

wrk git:master ❯ ./wrk -t12 -c400 -d30s http://some-amazon-hostname.com/rest/users/10                                               ✭ 
Running 30s test @ http://some-amazon-hostname.com/rest/users/10 
    12 threads and 400 connections 
    Thread Stats Avg  Stdev  Max +/- Stdev 
    Latency 333.42ms 322.01ms 3.20s 91.33% 
    Req/Sec 135.02  59.20 283.00  65.32% 
    48965 requests in 30.00s, 11.95MB read 
Requests/sec: 1631.98 
Transfer/sec: 407.99KB 
+0

Конечно, похоже, что виновником является ApacheBench! Я получаю 2821 запрос/секунду, используя wrk! Спасибо. Кстати, вы сравнили wrk с JMeter. Любые мнения? – Naresh

+0

никогда не использовался JMeter. Рассмотрите осаду, httperf и wrk в дополнение к ab, и wrk, вероятно, лучший и наиболее активно разработанный инструмент. –

+0

Посмотрите на эти инструменты. Еще раз спасибо за все ваше понимание. – Naresh

Смежные вопросы