Введение
Архитектура
Обработка входящих запросов
Коммуникация сервисов
Руководство пользователя
Получение данных из сервисов
Использование Панели управления
Туториалы
Получение данных из других сервисов
Построение истории отдельного пользователя
Классические модели атрибуции
Вероятностное прохождение воронки
Атрибуция по индексу активности
Воронки
X
Выберите раздел

Создание сервисов на TypeScript

Сервисы Rockstat — независимые процессы на Node.js, которые общаются между собой через Redis Pub/Sub сообщениями в формате JSON-RPC 2.0. Всё общее — конфигурация, логирование, метрики, клиент Redis, RPC — вынесено в библиотеку @rockstat/rock-me-ts (репозиторий rockme-framework).

Это руководство написано по трём рабочим сервисам платформы, на них же построены примеры:

  • chwriter — пишет все события в ClickHouse.
  • kafkastream — отправляет события в топики Kafka.
  • mmgeo — определяет регион по IP и разбирает User-Agent.

Роли сервисов

Входящие запросы принимает сервис Front. Он превращает запрос в событие с ключом маршрутизации вида in.gen.<service>.<name> и проводит его через три фазы (подробнее — Жизненный цикл и адресация):

  1. Обогащение (enricher). Front отправляет выбранные поля события в канал enrich и ждёт ответы от зарегистрированных обогатителей. Результаты дописываются в data события. Так работает mmgeo.
  2. Обработка (handler). Если на ключ события зарегистрирован удалённый обработчик, Front вызывает его и из ответа формирует HTTP-ответ клиенту.
  3. Рассылка слушателям (listener). Готовое событие уходит уведомлением в канал broadcast. Ответа Front не ждёт. Так работают chwriter и kafkastream.
РольКаналВызовКак Front узнаёт о сервисе
listenerbroadcastуведомление, без ответаникак, достаточно подписки на канал
enricherenrichзапрос, ответ за 200 мсрегистрация через __iamalive и __status
handlerимя сервисазапрос, ответ за 200 мсрегистрация через __iamalive и __status

Слушатель — самая простая роль: подписался на broadcast и обрабатывай поток. С него и стоит начинать новый сервис.

Что даёт rock-me-ts

  • AppConfig — конфигурация из config/*.yml с EJS-шаблонами и переменными окружения.
  • Logger — pino с дочерними логгерами на каждый класс (log.for(this)).
  • Meter — метрики в StatsD: tick, incr, gauge, time, timenote.
  • RedisFactory и RedisClient — клиент Redis на redis-fast-driver для Pub/Sub и команд.
  • RPCAdapterRedis и RPCAgnostic — транспорт и JSON-RPC: register, notify, request.
  • TheIds — идентификаторы: snowflake для событий, короткий счётчик для RPC, xxhash.
  • response — конструкторы ответов для Front: data, redirect, pixel, error, statical.
  • Константы шины: BROADCAST, SERVICE_DIRECTOR, METHOD_IAMALIVE, METHOD_STATUS.

Как устроен сервис

Во всех трёх сервисах один и тот же каркас. Точка входа src/index.ts импортирует AppServer, который при создании поднимает зависимости и подписывается на шину:

import 'reflect-metadata';
import {
  AppConfig, Logger, Meter, RedisFactory,
  RPCAdapterRedis, RPCAgnostic, AgnosticRPCOptions, BROADCAST
} from '@rockstat/rock-me-ts';

export class AppServer {
  constructor() {
    const config = new AppConfig<ModuleConfig>();   // config/*.yml + .env
    const log = new Logger(config.log);
    const meter = new Meter(config.meter);
    this.log = log.for(this);

    const redisFactory = new RedisFactory({ log, meter, ...config.redis });
    const channels = [config.rpc.name, BROADCAST];  // что слушаем
    const rpcOptions: AgnosticRPCOptions = { channels, redisFactory, log, meter, ...config.rpc };

    this.rpc = new RPCAgnostic(rpcOptions);
    this.rpc.setup(new RPCAdapterRedis(rpcOptions));

    this.setup().catch(exc => { this.log.error(exc); process.exit(1); });
  }

  async setup() {
    this.rpc.register(BROADCAST, async (msg) => { /* событие */ return {}; });
  }
}

export const appServer = new AppServer();

Дальше по разделу: