#node.js #node-fetch
#node.js #выборка узла
Вопрос:
Я тестировал выборку узла и решил использовать ее в проекте. В этом проекте я многократно извлекаю ресурс, до 600 раз в течение пары минут. Однако, когда я тестировал выборку узла, я обнаружил некоторое странное поведение: когда я зацикливал выборку, на выборку уходило все больше времени. Я доказал это, сгенерировав временные метки (см. Их Здесь ) для i
количества итераций. Это мой тестовый код:
for(let i = 0; i < 600; i ){
var start_time = new Date().getTime();
fetch('http://localhost:3000').then(a=>{
var time = (new Date().getTime() - start_time) 'ms'
console.log(time ' - ' i)
})
}
Есть ли способ обойти это? Я думаю, что это как-то связано с потоковой обработкой, есть ли обходной путь http
/ https
module?
Кроме того, есть ли причина i
, по которой номера итераций не в порядке?
Редактировать:
Я понял, что причина, по которой выборка резко ограничивалась postman и вызывала интенсивное ожидание, однако, когда я разместил простое приложение localhost и увеличил количество итераций до 60000, это заняло намного, намного больше времени, чем ожидалось, и сократилось примерно на 30000 итераций. Есть ли причина для этого? Вот конечные журналы:
15059ms - 15136
15059ms - 15137
15060ms - 15138
15060ms - 15140
15060ms - 15139
15061ms - 15142
15061ms - 15141
15061ms - 15143
15061ms - 15144
15062ms - 15145
15062ms - 15147
15062ms - 15146
15063ms - 15148
15063ms - 15149
15063ms - 15150
15064ms - 15152
15064ms - 15151
15064ms - 15153
15066ms - 15155
15066ms - 15154
15067ms - 15156
15067ms - 15157
15067ms - 15158
15067ms - 15159
15070ms - 15160
15073ms - 15161
15074ms - 15162
15074ms - 15163
15074ms - 15164
15074ms - 15165
15075ms - 15166
15075ms - 15167
15076ms - 15168
15076ms - 15169
15076ms - 15170
15077ms - 15171
15077ms - 15172
15077ms - 15173
15077ms - 15174
15078ms - 15175
15078ms - 15176
15078ms - 15177
15081ms - 15178
15081ms - 15179
15082ms - 15180
15082ms - 15181
15082ms - 15182
15083ms - 15183
15083ms - 15184
15083ms - 15185
15085ms - 15186
15086ms - 15187
15086ms - 15188
15086ms - 15189
15087ms - 34758
Есть ли причина, по которой: 1) итерации были значительно ниже ожидаемых и 2) время в мс значительно выше, чем ожидалось? Вот код для отредактированного теста:
for(let i = 0; i < 60000; i ){
var start_time = new Date().getTime();
get('http://localhost:3000').text().then(a=>{
var time = (new Date().getTime() - start_time) 'ms'
console.log(time ' - ' i)
})
}
Спасибо!
Комментарии:
1. Я бы подумал, что это ограничение скорости на стороне сервера
2. @Dominik ах, большое спасибо! Я протестирую это локально. Спасибо
3. @Dominik можете ли вы ответить на это своим комментарием? Я только что протестировал локально и подтвердил, что то, что вы сказали, было правдой, мой api ограничивал вызовы (честно говоря, я не понимаю, почему я установил для этого значение true). Большое спасибо, это прояснило большую загадку
Ответ №1:
Как упоминалось в комментариях, это, вероятно, связано с ограничением скорости на стороне сервера. Выполнение одного и того же теста локально, скорее всего, даст другой результат.
Редактировать: ваш локальный сервер через некоторое время будет заполнен запросами, и ему придется отрабатывать нагрузку, поэтому со временем она становится все медленнее и медленнее. Здесь вам поможет одно эмпирическое правило: http-запросы стоят дорого, и это первое узкое место, которого вам следует избегать.
Другой способ справиться с этим — добавить балансировщик нагрузки перед вашим сервером, чтобы вы могли масштабировать свой сервер на несколько машин.
В конце вам нужно выбрать между другим способом получения этих данных с сервера (возможно, использовать сокет-соединение, которое позволит вам получать данные только тогда, когда что-то изменилось на стороне сервера) или масштабированием ваших серверов.
Комментарии:
1. спасибо за ответ, хотя это правильный ответ, я отредактировал его, задав новый вопрос. Спасибо!
2. Я добавил новый раздел к ответу.
3. Большое спасибо! Извините, что не понял этого раньше.
4. Не извиняйтесь. Мы все многого не знаем 😉 Рад, что смог помочь
Ответ №2:
Это много вопросов в одном, но..
Почему это происходит?
Код выглядит нормально, скорее всего, веб-сайт, на который вы нажимаете, имеет ограничение скорости (вы можете нажимать на него только x раз в минуту, прежде чем он намеренно начнет замедлять ваши запросы, чтобы предотвратить DoS-атаки).
Есть ли обходной путь?
Если ваше замедление связано с ограничением скорости на веб-сайте (попробуйте другой без ограничения скорости, может быть, что-то вроде google.com сработало бы), то нет.
Есть ли причина, по которой номера итераций ( i
) не в порядке?
ДА. Вы отправляете все запросы асинхронно. Порядок, в котором регистрируется ваш вывод, зависит от времени получения ответов. Если они получены не по порядку, ваши i
s будут не по порядку.
Ответ на отредактированный вопрос:
Трудно понять, не зная больше о вашей локальной настройке. Замедление может быть вызвано рядом причин.
Возможные узкие места:
- Медленный ответ сервера. Возможно, серверу (конечной точке вашего HTTP-запроса) требуется много времени для ответа. Вы можете определить время отклика сервера, просмотрев журналы сервера, или попробовать веб-сервис, скорость которого не ограничена. Локальный сервер, например
nginx
, обслуживающий статические файлы, должен работать достаточно хорошо. - Замедление работы ОС. Существует ограничение на максимальное одновременное количество TCP-соединений, которое может обрабатывать операционная система. Поскольку вы открываете все эти соединения более или менее параллельно, ваши 60 тыс. запросов приближаются к максимуму в 65535 открытых соединений. Если вы используете локальный сервер на той же машине, то вы также используете сокет для ответа на каждое TCP-соединение — у вас будет вдвое меньше доступных сокетов от теоретического максимума.
libuv
Превышение предела пула потоков узла. Асинхронные задачи, которые выполняют ввод-вывод в узле, выполняются из пула потоков. Размер этого пула потоков по умолчанию равен 4, что означает, что только 4 задачи ввода-вывода могут выполняться асинхронно одновременно. Попробуйте увеличить этот предел, установивUV_THREADPOOL_SIZE
гораздо большее число (скажем,100
или400
), и посмотрите, получите ли вы пропорциональное увеличение количества запросов, которые могут быть отправлены без замедления, или уменьшение количества замедлений.- Сбор мусора в памяти. Ваш код не содержит много переменных, но библиотека, которую вы используете (
get
), может. Если это так, то изменение библиотеки или использование встроенных модулей узла для HTTP-выборки вызовут заметные изменения в замедлении
Комментарии:
1. спасибо за ответ, хотя это правильный ответ, я отредактировал свой пост, задав новый вопрос. Спасибо!
2. @imaginate, возможно, должен был быть новым вопросом, но я все равно ответил