Forwarded from Node.JS [ru] | Серверный JavaScript
Совет на ближайшие годы — изучайте ВАЙБ-КОДИНГ
ИИ уже пишет код, чинит баги, генерирует тесты, документацию и помогает запускать продукты быстрее, чем это делали классические команды разработки. И это уже не "будущее когда-нибудь", а реальность, которая меняет рынок уже сегодня
И те, кто научится вайбкодить сейчас, будут увереннее конкурировать на рынке и зарабатывать больше тех, кто по-прежнему делает всё вручную.
Стартовать с нуля поможет канал Вайб-кодинг. Там ребята круглосуточно мониторят более 320 российских и зарубежных источников и публикуют только главное: релизы, инструменты, гайды, курсы и практические кейсы.
Подписывайтесь, нас уже 45 тысяч: @vibecoding_tg
ИИ уже пишет код, чинит баги, генерирует тесты, документацию и помогает запускать продукты быстрее, чем это делали классические команды разработки. И это уже не "будущее когда-нибудь", а реальность, которая меняет рынок уже сегодня
И те, кто научится вайбкодить сейчас, будут увереннее конкурировать на рынке и зарабатывать больше тех, кто по-прежнему делает всё вручную.
Стартовать с нуля поможет канал Вайб-кодинг. Там ребята круглосуточно мониторят более 320 российских и зарубежных источников и публикуют только главное: релизы, инструменты, гайды, курсы и практические кейсы.
Подписывайтесь, нас уже 45 тысяч: @vibecoding_tg
Forwarded from Node.JS [ru] | Серверный JavaScript
Диагностика event loop stalls в production через monitorEventLoopDelay и async_hooks без гадания по p99 latency
Event loop stall важен там, где Node.js обслуживает API, воркеры, очереди и webhooks. Типичная ошибка - видеть рост latency и сразу винить БД, не проверив, не заблокирован ли сам JS thread.
Первый сигнал - monitorEventLoopDelay
Если p99 delay внезапно стал 200-500ms+, процесс не успевает выполнять callbacks вовремя: CPU-bound JS, sync I/O, тяжелый
Контекст дает async_hooks
Практический пример: при stall логируйте route/job из ALS, а не только глобальный p99. Так можно увидеть, что задержки появляются рядом с
Что отправлять в метрики
*
* CPU user/system
* RSS и heap used
* active handles/requests
* route/job labels - осторожно, без высокой кардинальности
Предупреждение: request id кладите в логи или трейсы, но не в метрики.
Важный нюанс
Нормальный flow: постоянно держать дешевый delay histogram, при threshold писать структурированный лог, при повторении включать profiler на короткое окно.
Вывод:
Event loop stall надо диагностировать в два шага: сначала измерить задержку loop, затем привязать ее к бизнес-контексту и только после этого идти в CPU profiling.
Event loop stall важен там, где Node.js обслуживает API, воркеры, очереди и webhooks. Типичная ошибка - видеть рост latency и сразу винить БД, не проверив, не заблокирован ли сам JS thread.
Первый сигнал - monitorEventLoopDelay
perf_hooks.monitorEventLoopDelay() дает histogram задержек event loop и дешево работает как постоянная production-метрика.import { monitorEventLoopDelay } from 'node:perf_hooks';
const h = monitorEventLoopDelay({ resolution: 20 });
h.enable();
setInterval(() => {
const p99 = h.percentile(99) / 1e6;
if (p99 > 100) {
log.warn({
event: 'event_loop_stall',
p99Ms: p99.toFixed(1),
maxMs: (h.max / 1e6).toFixed(1),
ctx: als.getStore()
});
}
h.reset();
}, 10_000).unref();Если p99 delay внезапно стал 200-500ms+, процесс не успевает выполнять callbacks вовремя: CPU-bound JS, sync I/O, тяжелый
JSON.parse, regexp, crypto, zlib или GC pressure.Контекст дает async_hooks
monitorEventLoopDelay отвечает на вопрос "есть ли stall", но не говорит "кто виноват". Для production связывайте AsyncLocalStorage с request id, route, job name, tenant или queue message id.Практический пример: при stall логируйте route/job из ALS, а не только глобальный p99. Так можно увидеть, что задержки появляются рядом с
POST /reports или конкретным batch job.Что отправлять в метрики
*
event_loop_delay_p50/p95/p99/max* CPU user/system
* RSS и heap used
* active handles/requests
* route/job labels - осторожно, без высокой кардинальности
Предупреждение: request id кладите в логи или трейсы, но не в метрики.
Важный нюанс
AsyncLocalStorage не профилирует CPU и не покажет строку кода. Он сохраняет контекст. Для строки нужен sampling profiler: inspector, --cpu-prof, perf/eBPF, Clinic или APM profiler.Нормальный flow: постоянно держать дешевый delay histogram, при threshold писать структурированный лог, при повторении включать profiler на короткое окно.
Вывод:
Event loop stall надо диагностировать в два шага: сначала измерить задержку loop, затем привязать ее к бизнес-контексту и только после этого идти в CPU profiling.
Forwarded from Node.JS [ru] | Серверный JavaScript
AsyncLocalStorage в production: как не потерять traceId через очереди, таймеры и connection pooling
Базовый слой
Создавайте контекст на входе в систему: HTTP, consumer, cron tick. Не ждите, что ALS сам перенесет его через процесс или брокер.
Очереди
Для in-memory очереди сохраняйте
Для Kafka, RabbitMQ, BullMQ, SQS ALS не участвует. Практический совет: кладите
Таймеры и scheduler'ы
Таймер, созданный внутри контекста, обычно его сохранит. Опасность появляется, когда callback зарегистрирован в одном месте, а вызван позже из scheduler'а.
Для cron/background задач создавайте новый
Connection pooling
Типичная ошибка - записывать
Connection живет дольше запроса и переиспользуется другим request'ом. Логируйте query через текущий ALS-контекст, а trace в БД передавайте на уровне конкретной операции или транзакции, например через transaction-local setting.
Вывод:
AsyncLocalStorage надежно держит контекст внутри await, промисов и I/O. Но в production traceId чаще теряется на границах: очереди, scheduler'ы, worker'ы и connection pool.Базовый слой
Создавайте контекст на входе в систему: HTTP, consumer, cron tick. Не ждите, что ALS сам перенесет его через процесс или брокер.
const als = new AsyncLocalStorage();
const withTrace = (traceId, fn) =>
als.run(Object.freeze({ traceId }), fn);
const getTraceId = () => als.getStore()?.traceId;
Очереди
Для in-memory очереди сохраняйте
store в момент enqueue и восстанавливайте при выполнении.function enqueue(payload) {
queue.push({ payload, store: als.getStore() });
}
function processJob(job) {
return job.store
? als.run(job.store, () => handleJob(job.payload))
: handleJob(job.payload);
}Для Kafka, RabbitMQ, BullMQ, SQS ALS не участвует. Практический совет: кладите
traceId в headers или payload и считайте это частью контракта сообщения.Таймеры и scheduler'ы
Таймер, созданный внутри контекста, обычно его сохранит. Опасность появляется, когда callback зарегистрирован в одном месте, а вызван позже из scheduler'а.
Для cron/background задач создавайте новый
traceId на каждый tick. Иначе получите "вечный" traceId процесса или случайный traceId старого запроса.Connection pooling
Типичная ошибка - записывать
traceId в client или connection object.client.traceId = getTraceId(); // плохо
Connection живет дольше запроса и переиспользуется другим request'ом. Логируйте query через текущий ALS-контекст, а trace в БД передавайте на уровне конкретной операции или транзакции, например через transaction-local setting.
Вывод:
AsyncLocalStorage работает хорошо только внутри async chain, а на production-границах traceId нужно явно фиксировать, передавать и восстанавливать.Forwarded from Node.JS [ru] | Серверный JavaScript
Graceful shutdown в Kubernetes: почему одного SIGTERM мало для keep-alive, HTTP/2 и фоновых задач
В production Pod редко умирает мгновенно: ingress, kube-proxy, LB и клиенты с keep-alive могут ещё слать трафик в terminating Pod. Частая ошибка - считать, что
Что реально нужно drain'ить
* HTTP/1.1 keep-alive соединения
* HTTP/2-сессии и активные stream'ы
* фоновые задачи: BullMQ, RabbitMQ, Kafka, cron, batch jobs
Иначе на rolling deploy получаются редкие 502/499, оборванные stream'ы и повторная обработка сообщений.
Staged shutdown для Node.js
Практический порядок:
* включить режим
*
* дать ingress/LB несколько секунд убрать Pod из ротации
* остановить новые TCP-соединения
* закрыть idle keep-alive
* дождаться активных запросов и задач в рамках бюджета
Важное предупреждение
HTTP/2 и фоновые задачи
Для HTTP/2 нельзя просто рубить socket: одна TCP-сессия содержит много stream'ов. Сначала отправляйте
Для workers на SIGTERM нужно остановить получение новых задач, не запускать новые cron-итерации, дождаться текущих и уметь отменять долгие операции через
Вывод:
Graceful shutdown - это не обработчик SIGTERM, а управляемый drain всего, что может продолжать работу после удаления Pod из ротации.
В production Pod редко умирает мгновенно: ingress, kube-proxy, LB и клиенты с keep-alive могут ещё слать трафик в terminating Pod. Частая ошибка - считать, что
server.close() уже дождался всех клиентов и задач.Что реально нужно drain'ить
* HTTP/1.1 keep-alive соединения
* HTTP/2-сессии и активные stream'ы
* фоновые задачи: BullMQ, RabbitMQ, Kafka, cron, batch jobs
Иначе на rolling deploy получаются редкие 502/499, оборванные stream'ы и повторная обработка сообщений.
Staged shutdown для Node.js
Практический порядок:
* включить режим
draining*
/readyz начинает отдавать 503* дать ingress/LB несколько секунд убрать Pod из ротации
* остановить новые TCP-соединения
* закрыть idle keep-alive
* дождаться активных запросов и задач в рамках бюджета
process.on('SIGTERM', async () => {
draining = true;
await sleep(5000);
server.close();
server.closeIdleConnections?.();
h2sessions.forEach(s => s.goaway());
await waitInFlight(25_000);
workers.abort();
server.closeAllConnections?.();
process.exit(0);
});Важное предупреждение
server.close() не означает "все клиенты ушли". Он только перестаёт принимать новые соединения. Уже открытые keep-alive соединения нужно отдельно закрывать через closeIdleConnections(), а в крайнем случае - через closeAllConnections().HTTP/2 и фоновые задачи
Для HTTP/2 нельзя просто рубить socket: одна TCP-сессия содержит много stream'ов. Сначала отправляйте
GOAWAY, чтобы запретить новые stream'ы, затем ждите завершения активных.Для workers на SIGTERM нужно остановить получение новых задач, не запускать новые cron-итерации, дождаться текущих и уметь отменять долгие операции через
AbortController.Вывод:
Graceful shutdown - это не обработчик SIGTERM, а управляемый drain всего, что может продолжать работу после удаления Pod из ротации.
Forwarded from Node.JS [ru] | Серверный JavaScript
18 июня(в четверг!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Frontend-разработчика.
Как это будет:
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Frontend-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_front_bot
Реклама.
О рекламодателе.
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from PSD | Дизайн-пространство
Дизайн бренда «Московское чаепитие»
В дизайне обращают на себя внимание яркие цвета и уникальные паттерны, а также лаконичные графические изображения столичных достопримечательностей — все это отражает самобытный характер бренда, его связь с Москвой.
: Ирина Угай
В дизайне обращают на себя внимание яркие цвета и уникальные паттерны, а также лаконичные графические изображения столичных достопримечательностей — все это отражает самобытный характер бренда, его связь с Москвой.
: Ирина Угай
Forwarded from Daily Coding 🔥
📖100 Go Mistakes and How to Avoid Them
🖋Harsanyi Teiva 2022
Книга «100 ошибок в Go и как их избежать» показывает, как заменить распространенные проблемы в программировании на Go идиоматичным и выразительным кодом. Вы изучите десятки интересных примеров и кейсов и научитесь выявлять ошибки, которые могут возникнуть в ваших собственных приложениях. Автор книги Тейва Харсаньи систематизирует методы предотвращения ошибок по удобным категориям — от типов данных и строк до параллелизма и тестирования.
💾 Скачать книгу
Daily Coding #книги #Go & Max
🖋Harsanyi Teiva 2022
Книга «100 ошибок в Go и как их избежать» показывает, как заменить распространенные проблемы в программировании на Go идиоматичным и выразительным кодом. Вы изучите десятки интересных примеров и кейсов и научитесь выявлять ошибки, которые могут возникнуть в ваших собственных приложениях. Автор книги Тейва Харсаньи систематизирует методы предотвращения ошибок по удобным категориям — от типов данных и строк до параллелизма и тестирования.
💾 Скачать книгу
Daily Coding #книги #Go & Max
Forwarded from Node.JS [ru] | Серверный JavaScript
Undici в production: почему исходящие HTTP-запросы должны иметь пулы, deadline и собственный backpressure
Пул создаётся на уровне приложения
Не заводите клиент внутри handler'а. Для критичных интеграций держите
Важно: тело ответа нужно дочитать или корректно сбросить, даже если оно не нужно. Иначе socket может не вернуться в пул вовремя.
connections - это capacity, а не магическое ускорение
Маленький пул даёт очередь и рост latency. Слишком большой пул перегружает upstream, плодит открытые socket'ы, упирается в NAT / ephemeral ports и ухудшает tail latency.
Практический ориентир: если upstream отвечает за 100 ms, то 32 соединения дают примерно 320 RPS без pipelining. Но финальный размер выбирайте по SLO, payload size, TLS, сети и rate limits.
Таймауты должны быть разными
Один общий timeout скрывает причину деградации.
-
-
-
-
Предупреждение:
Backpressure делайте до Undici
Не запускайте
Ограничивайте concurrency явно, например
Вывод:
Надёжный исходящий HTTP в Node.js - это не просто
fetch() в Node.js использует Undici, но в production часто нужен явный контроль: сколько socket'ов держим, сколько ждём upstream и что делаем, если входящий трафик быстрее внешнего API. Типичная ошибка - создавать запросы без лимитов и надеяться, что пул всё спасёт.Пул создаётся на уровне приложения
Не заводите клиент внутри handler'а. Для критичных интеграций держите
Pool per-origin и переиспользуйте его:import { Pool } from 'undici'
const api = new Pool('https://api.example.com', {
connections: 32,
pipelining: 1,
connectTimeout: 2_000,
headersTimeout: 3_000,
bodyTimeout: 10_000
})
async function callApi(payload) {
const { statusCode, body } = await api.request({
method: 'POST',
path: '/v1/process',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(payload),
signal: AbortSignal.timeout(12_000)
})
const text = await body.text()
if (statusCode >= 500) throw new Error(upstream ${statusCode})
return JSON.parse(text)
}Важно: тело ответа нужно дочитать или корректно сбросить, даже если оно не нужно. Иначе socket может не вернуться в пул вовремя.
connections - это capacity, а не магическое ускорение
Маленький пул даёт очередь и рост latency. Слишком большой пул перегружает upstream, плодит открытые socket'ы, упирается в NAT / ephemeral ports и ухудшает tail latency.
Практический ориентир: если upstream отвечает за 100 ms, то 32 соединения дают примерно 320 RPS без pipelining. Но финальный размер выбирайте по SLO, payload size, TLS, сети и rate limits.
Таймауты должны быть разными
Один общий timeout скрывает причину деградации.
-
connectTimeout - TCP/TLS connect-
headersTimeout - ожидание заголовков-
bodyTimeout - пауза между чанками body-
AbortSignal.timeout() - общий deadline операцииПредупреждение:
bodyTimeout не равен лимиту на весь response body.Backpressure делайте до Undici
Не запускайте
Promise.all(items.map(callApi)) на тысячи элементов. Undici поставит часть запросов в очередь, но память и давление на приложение уже выросли.Ограничивайте concurrency явно, например
MAX_IN_FLIGHT = 64. Он не обязан равняться connections: это лимит нагрузки на ваш сервис, а не только на socket pool.Вывод:
Надёжный исходящий HTTP в Node.js - это не просто
fetch(), а управляемые пулы, раздельные таймауты и backpressure до попадания запросов в Undici.Forwarded from Design Board
Не хотите ли ИКЕАшные 3Дшечки? Нашёл скриптик, который прямо на сайте ИКЕА добавляет кнопку и даёт дёрнуть модельки себе.
Forwarded from Node.JS [ru] | Серверный JavaScript
День сурка frontend-разработчика
Зарплата стоит, скучные задачи день за днем, календарь забит созвонами, которые не влияют вообще ни на что.
Откликаешься на вакансии, а в ответ тишина либо какие-то мутные конторы. На собесах вместо нормальной оценки навыков цирк с алгоритмами на скорость, как будто ты на олимпиаде, а не работу ищешь.
И самое неприятное, пока ты варишься в этом болоте, кто-то спокойно проходит собесы и уходит в Яндекс, VK или на хорошую Валютную удаленку без лишней драмы.
👋 Меня зовут Тихон, привет! Я — действующий Frontend-разработчик и ментор. Я за руку довожу до оффера на хорошую позицию в Big Tech и сопровождаю на испытательном сроке.
Также из учеников я собираю комьюнити, где уже более 220 frontend-разработчиков🫂
А в своем канале:
👉Объясняю, как проходить HR-фильтр и превращать отклики в реальные приглашения
👉Помогаю найти мотивацию, борюсь убеждениями, которые мешают развиваться
👉На примерах объясняю, как проходить собеседования, включая техничку
👉Разбираю резюме и делюсь лайфхаками, например как аккуратно “пинговать” рекрутеров
А еще регулярно публикую полезные материалы:
▪️Задачи, на которых валяться кандидаты
▪️База по микрофронтам
▪️Подборка из 100+ каналов с вакансиями для разработчиков
▪️100 вопросов, которые точно помогут тебе на собеседовании
▪️Чек лист проверки своего резюме
А еще у меня множество успешных кейсов и отзывов, найти их можно в канале.
Реклама, erid: 2W5zFJeWaNd ИП Галактионов Тихон Витальевич, ИНН 771618975809
Зарплата стоит, скучные задачи день за днем, календарь забит созвонами, которые не влияют вообще ни на что.
Откликаешься на вакансии, а в ответ тишина либо какие-то мутные конторы. На собесах вместо нормальной оценки навыков цирк с алгоритмами на скорость, как будто ты на олимпиаде, а не работу ищешь.
И самое неприятное, пока ты варишься в этом болоте, кто-то спокойно проходит собесы и уходит в Яндекс, VK или на хорошую Валютную удаленку без лишней драмы.
Есть классные проекты и сильные команды, где разработчиков действительно ценят, дают расти, поддерживают развитие и платят достойно и ты можешь туда попасть!
👋 Меня зовут Тихон, привет! Я — действующий Frontend-разработчик и ментор. Я за руку довожу до оффера на хорошую позицию в Big Tech и сопровождаю на испытательном сроке.
Также из учеников я собираю комьюнити, где уже более 220 frontend-разработчиков🫂
А в своем канале:
👉Объясняю, как проходить HR-фильтр и превращать отклики в реальные приглашения
👉Помогаю найти мотивацию, борюсь убеждениями, которые мешают развиваться
👉На примерах объясняю, как проходить собеседования, включая техничку
👉Разбираю резюме и делюсь лайфхаками, например как аккуратно “пинговать” рекрутеров
А еще регулярно публикую полезные материалы:
▪️Задачи, на которых валяться кандидаты
▪️База по микрофронтам
▪️Подборка из 100+ каналов с вакансиями для разработчиков
▪️100 вопросов, которые точно помогут тебе на собеседовании
▪️Чек лист проверки своего резюме
А еще у меня множество успешных кейсов и отзывов, найти их можно в канале.
Реклама, erid: 2W5zFJeWaNd ИП Галактионов Тихон Витальевич, ИНН 771618975809
Forwarded from Design Board
This media is not supported in your browser
VIEW IN TELEGRAM
На iOS у сайтов нет нормальной вибрации, поэтому кто-то просто спрятал нативный переключатель внутри кнопки — и оно работает, =).
Получаем костылёк для бр-р-р-отдачи на вебе, ссылка на гит внизу — project-fathom.vercel.app.
Получаем костылёк для бр-р-р-отдачи на вебе, ссылка на гит внизу — project-fathom.vercel.app.
Forwarded from PSD | Дизайн-пространство
Forwarded from Daily Coding 🔥
📖Beginning C# and .NET
🖋Perkins Benjamin, Reid Jon D. 2021
Язык C# был представлен миру, когда в 2002 году компания Microsoft анонсировала первую версию своей платформы .NET Framework. С тех пор его популярность резко возросла, и он стал основным языком для разработчиков настольных, веб-приложений, облачных и кроссплатформенных приложений, использующих .NET. Отчасти привлекательность C# обусловлена его понятным синтаксисом, который основан на синтаксисе C/C++, но упрощает некоторые вещи, которые раньше отпугивали некоторых программистов. Несмотря на это упрощение, C# сохранил мощь C++, и теперь нет причин не переходить на C#. Этот язык несложный и отлично подходит для изучения базовых приемов программирования. Простота изучения в сочетании с возможностями .NET Framework делает C# отличным выбором для начала карьеры программиста.
💾 Скачать книгу
Daily Coding #книги #Csharp & Max
🖋Perkins Benjamin, Reid Jon D. 2021
Язык C# был представлен миру, когда в 2002 году компания Microsoft анонсировала первую версию своей платформы .NET Framework. С тех пор его популярность резко возросла, и он стал основным языком для разработчиков настольных, веб-приложений, облачных и кроссплатформенных приложений, использующих .NET. Отчасти привлекательность C# обусловлена его понятным синтаксисом, который основан на синтаксисе C/C++, но упрощает некоторые вещи, которые раньше отпугивали некоторых программистов. Несмотря на это упрощение, C# сохранил мощь C++, и теперь нет причин не переходить на C#. Этот язык несложный и отлично подходит для изучения базовых приемов программирования. Простота изучения в сочетании с возможностями .NET Framework делает C# отличным выбором для начала карьеры программиста.
💾 Скачать книгу
Daily Coding #книги #Csharp & Max