Node.js Streams.

По fix protocol у нас общаются 2 наших системы для real-time трейдинга. Грубо говоря в fix protocol входят 2 большие категории сообщений: маркеты и ордера. При тестировании fix protocol мы столкнулись с проблемой - очень большое количество данных. Если писать логи в фаил - 2-3 гигабайта пишется на диск за 1 секунду!!!

Естественно, все события, которые приходят нам не нужны. И тут на сцену выходят Streams. Поскольку все, что приходит по сети, наследуется от Streams, а стримы можно выстраивать в конвеер через pipe или pipeline. Первым делом мы попытались отсечь ненужное - обновления по маркетам. Для наглядности мы сделаем простую программу, которая будет читать входной поток пользователя из консоли и убирать какую-то букву (например «о»).

import { createWriteStream } from 'node:fs' import { Transform, pipeline } from 'node:stream'

pipeline( process.stdin, new Transform({ transform(chunk, encoding, callback) { const str = Buffer.from(chunk).toString('utf8') const transformed = str.replace(/o/g, '') callback(null, transformed) }, }), createWriteStream('./log.txt'), (err) => { if (err) { console.error('Pipeline error:', err) process.exit(1) } }, )

Что нам это дает? Таким образом мы можем отсекать ненужные события, тем самым сократив их кол-во в разы. Для этого мы удалили обновления маркетов, что составляло наибольшее кол-во событий. Вместо 2-3 Gb/sec мы теперь пишем 200-300Mb/sec - разница в 10-12 раз в среднем! Далее мы начали смотреть, какие из получившихся событий можно еще усечь. Проанализировав полученные логи, мы заметили, что по фикс протоколу приходят все события по пользователям и было решено сделать агрегацию полученного потока по разным категориям, например: "самый большой ордер", "среднее значение исполнения ордера(цена покупки)" и т.д. Таких показателей около 10.

Благодаря этому запись в фаил сократилась до нескольких строк.По сути мы ждем, пока стрим не закроется, а уже после закрытия мы забираем у него последние данные. А для локального запуска мы даже можем в фаил не писать, а сделать простой TUI. Не забываем, что большое кол-во фаилов одной ноде будет тяжело обработать, поэтому добавляем воркеров в помощь.

По сути я рассказал класическую задачу про Map-Reduce. Это было увлекательным путешествием на 5 минут, которое писалось довольно длительно. Наверняка, вы ожидали здесь еще что-то увидеть про LLM и то, как они помогли в написании кода? Однако скажу лишь то, что LLM больше помогла в разборе фаилов, чем в написании кода. На мой взгляд, решения таких узких задач не так уж и много в открытом доступе, поэтому LLM то и дело, что галюцинировала. Зато в анализе большого фаила с FIX логами она очень сильно помогла. Поскольку данные однотипные и похожи на GRPC, только более читабельное.

#nodejs #js @haradkou_sdet

Node.js Streams.
По fix protocol у нас общаются 2 наших системы для real-time трейдинга. Грубо говоря в fix protocol входят 2 большие категории сообщений: маркеты и ордера | Сетка — социальная сеть от hh.ru