Vladimir
ну экспресс то при чем
Vlad
Ну несколько багов мы в нем таки нашли в то время... Это года два или три назад было вроде
Неважно когда. Мне интересно как определили, что экспресс течёт а не ваш код или другие депсы
hamper 𓅝
Ставили чистый экспресс и на недельку под максимальную нагрузку жметром
hamper 𓅝
Кстати возможно текла нода, 0.8 вообще глючноватая была местами
Максим
Impress Application Server кто-то юзает?
Artur
hamper 𓅝
на 4 ноде 10к рпс экспресс держал спокойно
Ну может тогда его и возьму, а то коа пока выглядит подозрительно.
Vladimir
> @p_hamper Ну за неделю нагрузки в 6к запросов в секунду там Гб вытекал куда то.. это меньше байта на запрос. Нетипично для утечек
hamper 𓅝
> @p_hamper Ну за неделю нагрузки в 6к запросов в секунду там Гб вытекал куда то.. это меньше байта на запрос. Нетипично для утечек
Ну это все на столько давно было что сейчас уже причины искать скорее всего бесполезно будет.
Vladimir
Просто чаще всего, когда говорят об утечках, на самом деле нет никаких утечек
hamper 𓅝
Ну по крайней мере тогда положение спасло переписывание всего на connect и дальше разбираться не стали.
Vladimir
цикличные ссылки не вызывают утечек
hamper 𓅝
Цикличные ссылки и структура из котороый повисает только небольшая часть?
Ну тогда человек который отвечал за проект решил тупо переписать все на connect когда за несколько дней причину не нашли, так что сложно сказать что то определенное уже...
hamper 𓅝
Может там просто очередь запросов не успевала разбираться и накапливалась потихоньку...
Evgeny
Я не знаю как что устроено внутри экспресса, но ситуацию когда каакя-то структура будет подтекать только небольшой частью за счет циклических ссылок и повисащих хвостов - видел
Evgeny
Естественно что на один из узлов есть ссылка снаружи
Vladimir
Еще раз - циклические ссылки не приводят к утчечкам
Evgeny
Если на них есть внещние ссылки?
Vladimir
Следовательно, увидеть это проблематично
Vladimir
На кого - на них?
Evgeny
На одну ноду этого циркуляр референса
Vladimir
Циркулярность тогда причем?
hamper 𓅝
Для http времени на написание обертки много уйдет, наверное экспресс возьму, на коа было бы писать проще но на счет него я не знаю на счет производительности и стабильности.
Evgeny
Ничего. Я обьяснял как может быть меньше одного байта утечки на один запрос
Evgeny
Это никак не связано с экспрессом
Vladimir
> @NordLuf Я обьяснял как может быть меньше одного байта утечки на один запрос и это не как не объясняет <1 байта
Vladimir
<1 байта можно объяснять только логикой, которая выполняет действия реже чем 1 раз на запрос, причем сильно реже
Vladimir
в экспрессе нет такой логики
Vladimir
> @klond90 Да ну роутер написать дело получаса в общем то его можно и не писать, а просто юзать регэкспы
Evgeny
<1 байта можно объяснять только логикой, которая выполняет действия реже чем 1 раз на запрос, причем сильно реже
Либо, что какая-то структура заполняется и опустощается чанками, и на 1000, например, запросов остается повисшим указатель на 10 байт, остальные части структуры удаляются
Vladimir
да, но в экспрессе ничего такого нет
Evgeny
ОК
hamper 𓅝
Да скорее всего проблема либо в самой ноде была (в одной из версий реально помню что то вытекало сразу на том же коде) либо в логике.
hamper 𓅝
Свет вырубили в доме, видимо имеет смысл спать...
Evgeny
да, но в экспрессе ничего такого нет
И в прошлых версиях, из которых еще не повыдергивали модули, тоже не было? Речь то про несколько лет назад
Vladimir
нет
Evgeny
ОК
hamper 𓅝
Погуглил бенчмарки, у всех коа слегка обгоняет экспресс таки
Anonymous
Сравнивая express и koa надо учесть еще самый большой недостаток express - то что на его миддлварах нельзя построить конвеерную обработку запроса
Anonymous
В экспрессе нельзя сделать конвейерную обработку запросов потому что express отбрасывает значения middleware-функции и вот такое без патча экспресса сделать не получится //log requests middlewares.push(async(next, req, res) => { console.log('request start:', req.method, req.url); var response = await next(); console.log('request send:', response); res.end(JSON.stringify(response)); console.log('request end:', req.method, req.url); }); //catch errors middlewares.push(async(req, res, next) => { try { return await next(); } catch (e) { console.log('error:', e); res.status(400); return {error: e.message}; } }); middlerawe.push(staticServer) //connect to database middlewares.push(async(next, req, res) => { req.db = await new DB(schema); req.data = {}; try { return await next(); } catch (err) { await req.db.disconnect(); throw err; } }); middlerawe.push(cookieParser) middlewares.push(getCurrentUserOrCreateGuest) middlerawe.push(bodyParser) //map request info to crud operation middlewares.push(async(next, req, res) => { var [table, id] = req.url.split('/').slice(1); var dbActions = { "GET": 'get', "POST": 'add', "PUT": 'update', "DELETE": 'delete' }; req.data.action = dbActions[req.method]; req.data.table = table; req.data.id = id; return await next(); }); //process request in database middlewares.push(async(next, req, res) => { var {table, id, action} = req.data; if(!table) throw new Error('no table'); var index = req.query.index; var body = req.body; if (action == 'get') { return await req.db.get(table, id, {index}) } if (action == 'add') { return await req.db.add(table, body) } if (action == 'update') { return await req.db.update(table, id, body) } if (action == 'delete') { return await req.db.delete(table, id) } });
Vint
Сравнивая express и koa надо учесть еще самый большой недостаток express - то что на его миддлварах нельзя построить конвеерную обработку запроса
Но это трешак какой-то в примере показан. Смесь всего и вся. Такое можно повторить через единый толстый контроллер, но зачем?
hamper 𓅝
Кладешь в req промис и ловишь его после next
hamper 𓅝
В поле req точнее, как в контекст
Ilya
довольно странная трабла
Vint
Ну, именно. Все middleware в express работают над заполнением req/res. Обработка ошибок чуть отдельно. Всё.
Ilya
делай поиск по пустому селектору в монге, где 0 записей - все норм стоит к курсору, который возвращает поиск, применить сортировку, и он мне выдает следующее
Ilya
Vint
А stack ошибки где?
Anonymous
Кладешь в req промис и ловишь его после next
с асинками такое не пройдет потому что они как раз возвращают промис который отбрасывается экспрессом
Ilya
А stack ошибки где?
что-то я давно не ловил трейсы у промисов
Ilya
ща продебажу
Vint
с асинками такое не пройдет потому что они как раз возвращают промис который отбрасывается экспрессом
Пишется некоторый враппер над контроллерами. То же самое, как обмазывать express промисами.
Vint
ща продебажу
Промисы нативные или bluebird, например?
Denis
Я как-то спрашивал про инструмент для отслеживания используемых версий пакетов и смотреть Change Log по мере того, как будут новые релизы. Сейчас нашёл такой инструмент: https://david-dm.org/expressjs/express
Ilya
ща апдейтну ноду
hamper 𓅝
с асинками такое не пройдет потому что они как раз возвращают промис который отбрасывается экспрессом
Разве нельзя сделать в вызвваемом мидлваре req.res = new Promise... А в ввзывающем req.res.then?
Anonymous
Но это трешак какой-то в примере показан. Смесь всего и вся. Такое можно повторить через единый толстый контроллер, но зачем?
Почему же трешак? Идет обработка запроса в отдельных миддлварах каждый из которых отвечает за свою область. Один логирует, второй обрабатывает ошибки, третий парсит боди, чертвертый будет валидировать данные и потом уже запрос попадает в базу данных после которого еще одна миддлварка будет фильтровать данные для отдачи юзеру. В чем же треш? Я просто объеденил их для наглядности в одном файле
Vladimir
мидлвари не для этого
Vladimir
они строго для работы с http
Ilya
Промисы нативные или bluebird, например?
юзаю, если что, node-mongodb-native
Anonymous
Разве нельзя сделать в вызвваемом мидлваре req.res = new Promise... А в ввзывающем req.res.then?
через чистые промисы да, все можно а вот если через async-await то app.use(async (req,res,next)=>{ console.log('start'); await next() console.log('end') })не получится потому что async возращает промис который отбрасывается экспрессом
hamper 𓅝
А при чем тут асинк? мы же про экспресс говорим или там асинки поддерживать стали?
Vint
юзаю, если что, node-mongodb-native
Такого не трогал. В общем, нужен stack trace и тогда будет проще понять, что и где. Подпиши process на unhandledRejection, там можно будет найти.
Ilya
не ловит
Anonymous
Как раз в этом объединении и проблема. static и DB в одной цепочке - зачем? Туда же куки и остальное.
а в чем проблема? в любом случае нужно отфильтровать запросы которые относятся к файлам и те которые относятся к апи, вот этим и занимается миддлварка которая перехватывает запросы
Vint
через чистые промисы да, все можно а вот если через async-await то app.use(async (req,res,next)=>{ console.log('start'); await next() console.log('end') })не получится потому что async возращает промис который отбрасывается экспрессом
Чистые промисы тоже не получится сразу. Поэтому я и сказал про враппер. Но без патчинга самого express. async не пробовал ещё прикрутить, ради интереса потом напишу.
Anonymous
А при чем тут асинк? мы же про экспресс говорим или там асинки поддерживать стали?
поддержка асинков как раз и заключается в том чтобы не отбрасывать значения миддлваров, вот в моем пуллреквесте я исправил эту проблему экспресса и он волшебным образом стал поддерживать асинки https://github.com/expressjs/express/pull/3138 но только его не приняли(
Anonymous
Фильтровать надо на уровне роутов, а не вызывая кучу бесполезных (для данного uri) мидлварей.
так они и не вызываются, запрос просто сразу обрабатывается и не проходит дальше по конвееру
Vint
а в чем проблема? в любом случае нужно отфильтровать запросы которые относятся к файлам и те которые относятся к апи, вот этим и занимается миддлварка которая перехватывает запросы
По сути, идеальная схема роутинга - это конфиг с перечислением отношений роут - список middleware. Где-то куки нужны, где-то raw-body, где-то passport, например. Где-то пучок всего. Но это не на каждый проект годится, естественно.
Ilya
короче забил на ошибку, заюзал сортировку по массиву
hamper 𓅝
А я про такой код говорил: const express = require('express') const app = express() app.use((req, res, next) => { next() req.pr.then(x => console.log(x)) }) app.get('/', (req, res) => { req.pr = Promise.resolve(1) res.send('Hello World!') }) app.listen(3000)
Vint
так они и не вызываются, запрос просто сразу обрабатывается и не проходит дальше по конвееру
Каждый раз дёргается staticServer, файла нет - идём в БД. Так что ли? Кстати, зачем там каждый раз connect и disconnect? Что за хранилище, пула нет?