tgoop.com/super_oleg_dev/202
Last Update:
Возможно будет история еще об одной утечке, связанной с Async Local Storage, но как минимум хочу рассказать про интересный кейс, связанный с отладкой этой проблемы.
Мы используем Fastify в качестве веб-сервера для Tramvai, разбираясь с утечкой поставил логи на хуки onRequest и onResponse.
Даю нагрузку на приложение через autocannon, обнаружил что onResponse логов меньше чем onRequest, хотя ответы от приложения приходят все.
Хорошо (хоть и поздно) заметил что не хватает ровно столько onResponse сколько запросов к параллельному вызову я указал для autocannon, условные 10 последних из 100 отправленных.
Похоже, autocannon не дожидается последнюю пачку запросов до конца, и прерывает их до того как стрим ответа будет завершен.
Обнаружил это через подписку на события finish
и close
объекта Request - оказалос что finish так же не вызывается эти 10 раз, а последние 10 close прилетают пачкой одновременно.
app.addHook('onRequest', async (request, reply) => {
request.raw.on('finish', () => { ... });
request.raw.on('close', () => { ... });
})
Понаставил логов в fastify, посмотрел исходники, и оказывается хук
onResponse
вызывается как раз на событие finish
.И это получается дефолтное поведение в Node.js, если Request был отменен клиентом (request.aborted), событие finish не срабатывает, даже когда reply.send(...) будет вызван после отмены и фактически завершит стрим.
Это кстати можно мониторить, есть гайд у fastify - https://fastify.dev/docs/latest/Guides/Detecting-When-Clients-Abort/#detecting-when-clients-abort
Вот такой вот случайно обнаруженный сайд-эффект из-за нюансов работы autocannon, который в теории может воспроизводиться и на продакшене, и получается onResponse не самый надежный вариант для очистки чего-либо после завершения запроса.
BY SuperOleg dev notes
Share with your friend now:
tgoop.com/super_oleg_dev/202