Как отдавать данные по акциям
Что проверяют
Это вопрос на системный дизайн, и первым делом смотрят, зададите ли вы уточняющие вопросы: сколько клиентов и бумаг, как часто меняется цена, нужна ли история. Следом почти всегда спрашивают, что будет с медленным клиентом и как пережить переподключение.
Как отвечать
Уточните, что речь о биржевых котировках, а не о маркетинговых промоакциях, и разделите данные на два потока:
- снимок и история: последняя цена, свечи, справочник бумаг. Отдаются запросом через REST или gRPC. С Go 1.22 стандартный
http.ServeMuxпонимает шаблоны видаGET /stocks/{ticker}иr.PathValue("ticker"). Историю хранят в колоночной базе вроде ClickHouse, горячие значения в памяти или в Redis; - поток обновлений: WebSocket, SSE или gRPC server streaming. Клиент подписывается на свои тикеры, а не получает весь рынок.
Внутри сервис-приёмник читает поставщика данных, нормализует и публикует в брокер (Kafka, NATS). Шлюзы подписаны на брокер, держат соединения клиентов и масштабируются горизонтально.
Детали, которые отличают сильный ответ:
- медленный клиент: у соединения своя горутина-писатель и буферизованный канал. Рассылка пишет через
selectсdefaultи не блокируется, переполнил буфер, отключаем; - прореживание: для котировки важна последняя цена, шлюз шлёт по тикеру не каждый тик, а свежее значение раз в 200 мс;
- снимок и дельты: после переподключения клиент получает текущее состояние, дальше изменения с порядковым номером, чтобы заметить пропуск;
- деньги: цену не держат во
float64, берут целое в минимальных единицах или десятичный тип.
Где спотыкаются
Рассылают обновления одним циклом по всем сокетам. Один клиент на плохой сети тормозит доставку остальным.
Пишут в одно соединение gorilla/websocket из нескольких горутин. Библиотека допускает только одного писателя за раз, под нагрузкой это паника.
Предлагают клиентам опрашивать REST раз в секунду. На тысячах пользователей это лишняя нагрузка и всё равно задержка до секунды.