docs(course): согласованы уроки со startup-history
- Зачем: - курс должен проходить на чистом стенде без архивного сида и скрытых шагов. - Что: - уроки 00, 01 и 05 согласованы с генераторными топиками, no-live default и consumer lag. - упражнение с kafka_msg_ts переведено на повторную заливку без сброса схемы. - учебный путь в операционной документации ведёт через startup-history. - Проверка: - make generated-history-analytics; make up; doc rg checks; git diff --check.
This commit is contained in:
+4
-3
@@ -103,9 +103,10 @@ docker compose exec -T airflow-webserver airflow dags unpause etl_pipeline
|
|||||||
- Параметры:
|
- Параметры:
|
||||||
- `full_refresh` (`bool`, default `true`) — очистить DDS перед загрузкой
|
- `full_refresh` (`bool`, default `true`) — очистить DDS перед загрузкой
|
||||||
- `wait_stg_timeout_sec` (`int`, default `600`, minimum `30`) — сколько секунд задача `wait_for_stg_data` ждёт появления данных в STG, прежде чем упасть по таймауту
|
- `wait_stg_timeout_sec` (`int`, default `600`, minimum `30`) — сколько секунд задача `wait_for_stg_data` ждёт появления данных в STG, прежде чем упасть по таймауту
|
||||||
- Зависимость: требует наличия данных в STG (от `kafka_load` или `make data`)
|
- Зависимость: требует наличия данных в STG. В штатном сценарии STG наполняет
|
||||||
- В штатном сценарии STG наполняет `make generated-history-analytics` через
|
`make generated-history-analytics` через backfill генератора.
|
||||||
backfill генератора.
|
- Архивные `kafka_load` и `make data` оставлены только для ручных экспериментов
|
||||||
|
и старых проверок.
|
||||||
- Гейт целостности DDS: `check_dds_integrity` считает события без клика, а
|
- Гейт целостности DDS: `check_dds_integrity` считает события без клика, а
|
||||||
`assert_dds_integrity` роняет DAG при `orphan_events > 0`. Проверка идёт после
|
`assert_dds_integrity` роняет DAG при `orphan_events > 0`. Проверка идёт после
|
||||||
`load_dds` и до `load_dm_summary`, чтобы DM не собирался поверх нарушенной связи
|
`load_dds` и до `load_dm_summary`, чтобы DM не собирался поверх нарушенной связи
|
||||||
|
|||||||
@@ -72,6 +72,25 @@
|
|||||||
- **Идёшь с ментором** — еженедельный созвон покрывает несколько уроков сразу: туда
|
- **Идёшь с ментором** — еженедельный созвон покрывает несколько уроков сразу: туда
|
||||||
несёшь затыки и ответы «своими словами» из тех же секций «Проверь себя».
|
несёшь затыки и ответы «своими словами» из тех же секций «Проверь себя».
|
||||||
|
|
||||||
|
## Проверка чистого маршрута
|
||||||
|
|
||||||
|
Перед проверкой уроков 0, 1 и 5 подними стенд с нуля:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make generated-history-analytics
|
||||||
|
make up
|
||||||
|
```
|
||||||
|
|
||||||
|
Что должен подтвердить человек:
|
||||||
|
|
||||||
|
- урок 0: в Kafka UI видны четыре топика событий и понятны служебные топики
|
||||||
|
генератора;
|
||||||
|
- урок 1: после `CLEAN_START=0 make generated-history-analytics` учебная колонка
|
||||||
|
`kafka_msg_ts` не пропадает и заполняется;
|
||||||
|
- урок 5: Prometheus targets `clickhouse`, `kafka`, `airflow` находятся в `UP`,
|
||||||
|
а `Kafka No Messages Produced` трактуется с учётом того, запущен live-генератор
|
||||||
|
или только стартовая история.
|
||||||
|
|
||||||
## Границы
|
## Границы
|
||||||
|
|
||||||
Материалы под конкретного менти (привязка к работодателю, легенда, подготовка к
|
Материалы под конкретного менти (привязка к работодателю, легенда, подготовка к
|
||||||
|
|||||||
@@ -60,9 +60,17 @@ make up
|
|||||||
- `geo_events` — гео;
|
- `geo_events` — гео;
|
||||||
- `location_events` — местоположение.
|
- `location_events` — местоположение.
|
||||||
|
|
||||||
Рядом может быть служебный топик `__consumer_offsets` (если включён показ внутренних
|
Рядом могут быть служебные топики:
|
||||||
топиков) — его Kafka использует сама, мы его не трогаем. У каждого нашего топика в колонке
|
|
||||||
с партициями стоит **1**: топик маленький, делить не на что.
|
- `__consumer_offsets` — внутренний топик Kafka. В нём Kafka хранит прогресс
|
||||||
|
consumer-групп;
|
||||||
|
- `generator_state` — слепок состояния генератора на правой границе стартовой истории.
|
||||||
|
По нему live-продолжение понимает, откуда продолжать тот же мир;
|
||||||
|
- `generator_startup_history_manifest` — паспорт стартовой истории: seed, границы
|
||||||
|
модельного времени и контрольные числа.
|
||||||
|
|
||||||
|
Служебные топики нужны стенду, но в упражнениях курса мы их не меняем. У каждого нашего
|
||||||
|
топика событий в колонке с партициями стоит **1**: топик маленький, делить не на что.
|
||||||
|
|
||||||
**Сообщения в топике.** Открой `browser_events` → вкладку *Messages*. Это и есть события
|
**Сообщения в топике.** Открой `browser_events` → вкладку *Messages*. Это и есть события
|
||||||
стенда. У каждого сообщения видно:
|
стенда. У каждого сообщения видно:
|
||||||
@@ -127,7 +135,7 @@ consumer-группа помнит, где остановилась: дочит
|
|||||||
|
|
||||||
| Действие | Где смотреть | Что ожидать |
|
| Действие | Где смотреть | Что ожидать |
|
||||||
|----------|--------------|-------------|
|
|----------|--------------|-------------|
|
||||||
| открыть список топиков | Kafka UI → *Topics* | 4 топика событий (`*_events`), у каждого 1 партиция |
|
| открыть список топиков | Kafka UI → *Topics* | 4 топика событий (`*_events`) и, возможно, служебные топики генератора |
|
||||||
| открыть `browser_events` | вкладка *Messages* | сообщения с offset'ами 0, 1, 2, …; в Value — JSON события |
|
| открыть `browser_events` | вкладка *Messages* | сообщения с offset'ами 0, 1, 2, …; в Value — JSON события |
|
||||||
| сравнить два времени | Value (`event_timestamp`) vs Kafka *Timestamp* | время события и время доставки в Kafka различаются |
|
| сравнить два времени | Value (`event_timestamp`) vs Kafka *Timestamp* | время события и время доставки в Kafka различаются |
|
||||||
| открыть consumers | Kafka UI → *Consumers* | 4 группы `ch_stg_*`, статус `STABLE`, по 1 участнику |
|
| открыть consumers | Kafka UI → *Consumers* | 4 группы `ch_stg_*`, статус `STABLE`, по 1 участнику |
|
||||||
|
|||||||
@@ -189,20 +189,20 @@ SELECT
|
|||||||
FROM stg.kafka_browser_raw;
|
FROM stg.kafka_browser_raw;
|
||||||
```
|
```
|
||||||
|
|
||||||
**Перезаливаем срез, чтобы новая колонка заполнилась.** Сначала чистим таблицу — иначе
|
**Перезаливаем срез, чтобы новая колонка заполнилась.** Сначала чистим только таблицу
|
||||||
рядом останутся строки из секции 2, вставленные ещё *до* `ADD COLUMN`, и в них
|
приёмника — иначе рядом останутся строки из секции 2, вставленные ещё *до*
|
||||||
`kafka_msg_ts` будет пустой (`1970-01-01`):
|
`ADD COLUMN`, и в них `kafka_msg_ts` будет пустой (`1970-01-01`):
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
TRUNCATE TABLE stg.browser_raw;
|
TRUNCATE TABLE stg.browser_raw;
|
||||||
```
|
```
|
||||||
|
|
||||||
Затем возвращаем стенд в чистое состояние и заново создаём стартовую историю, чтобы
|
Затем повторно создаём стартовую историю **без очистки volumes**. Это важно:
|
||||||
Kafka-движок прочитал сообщения уже с новой схемой:
|
`CLEAN_START=0` сохраняет твою новую колонку и пересозданное MV, но добавляет свежие
|
||||||
|
сообщения в Kafka, чтобы ClickHouse прочитал их уже с новой схемой.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make generated-history-analytics
|
CLEAN_START=0 make generated-history-analytics
|
||||||
make up
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Смотрим результат:**
|
**Смотрим результат:**
|
||||||
@@ -232,7 +232,7 @@ ALTER TABLE stg.browser_raw DROP COLUMN kafka_msg_ts;
|
|||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make ddl # пересоздаёт эталонный MV из 10_stg.sql — схема снова как в репозитории
|
make ddl # пересоздаёт эталонное MV из 10_stg.sql, схема снова как в репозитории
|
||||||
```
|
```
|
||||||
|
|
||||||
Если запутался в состоянии — всегда есть полный чистый прогон:
|
Если запутался в состоянии — всегда есть полный чистый прогон:
|
||||||
|
|||||||
@@ -81,16 +81,19 @@ make up
|
|||||||
|
|
||||||
Открой Prometheus: `http://localhost:9090`. В меню зайди в **Status → Targets**.
|
Открой Prometheus: `http://localhost:9090`. В меню зайди в **Status → Targets**.
|
||||||
|
|
||||||
Ожидаем три job:
|
Ожидаем основные job:
|
||||||
|
|
||||||
| Job | Target внутри Docker | Что это значит |
|
| Job | Target внутри Docker | Что это значит |
|
||||||
|-----|----------------------|----------------|
|
|-----|----------------------|----------------|
|
||||||
| `clickhouse` | `clickhouse:9126` | ClickHouse отдаёт встроенный Prometheus endpoint |
|
| `clickhouse` | `clickhouse:9126` | ClickHouse отдаёт встроенный Prometheus endpoint |
|
||||||
| `kafka` | `kafka-exporter:9308` | `kafka-exporter` подключился к Kafka и отдаёт метрики |
|
| `kafka` | `kafka-exporter:9308` | `kafka-exporter` подключился к Kafka и отдаёт метрики |
|
||||||
| `airflow` | `statsd-exporter:9102` | `statsd-exporter` отдаёт метрики Airflow в формате Prometheus |
|
| `airflow` | `statsd-exporter:9102` | `statsd-exporter` отдаёт метрики Airflow в формате Prometheus |
|
||||||
|
| `generator` | `generator:9109` | live-генератор отдаёт свои метрики, только когда явно запущен |
|
||||||
|
|
||||||
У всех трёх состояние должно быть `UP`. Если один target `DOWN`, Grafana дальше будет показывать
|
У `clickhouse`, `kafka` и `airflow` состояние должно быть `UP`. `generator` на штатном
|
||||||
`No data` или старые значения.
|
backfill-only стенде может быть `DOWN`, потому что `make up` не запускает live-генератор.
|
||||||
|
Это нормально для курса до явного `make generator-continue`. Если один из трёх основных
|
||||||
|
target `DOWN`, Grafana дальше будет показывать `No data` или старые значения.
|
||||||
|
|
||||||
То же можно проверить из терминала:
|
То же можно проверить из терминала:
|
||||||
|
|
||||||
@@ -157,8 +160,14 @@ URL: `http://localhost:3000/d/kafka-overview/kafka-overview`
|
|||||||
- **Partitions** и **Partition Offsets (Current)** — текущие offset-ы по партициям.
|
- **Partitions** и **Partition Offsets (Current)** — текущие offset-ы по партициям.
|
||||||
|
|
||||||
**Consumer lag** — это разница между тем, что уже лежит в топике, и тем, что consumer group
|
**Consumer lag** — это разница между тем, что уже лежит в топике, и тем, что consumer group
|
||||||
успела прочитать. В нашем стенде lag обычно быстро возвращается к нулю: данных мало, ClickHouse
|
успела прочитать. В нашем стенде ClickHouse обычно читает быстро, поэтому большой устойчивый
|
||||||
читает быстро. Если lag растёт и не снижается, downstream не успевает за Kafka.
|
lag не ожидается.
|
||||||
|
|
||||||
|
Есть важная оговорка из урока 0: ClickHouse-движок не всегда показывает свой прогресс как
|
||||||
|
обычная Kafka-группа. Поэтому в Kafka UI колонки offset/lag у `ch_stg_*` могут быть пустыми,
|
||||||
|
а в Grafana панель lag может быть пустой или нулевой. Это не конфликт между уроками. Для
|
||||||
|
точной проверки чтения со стороны ClickHouse смотри `system.kafka_consumers`, а Grafana здесь
|
||||||
|
используй как общий сигнал: появился ли большой lag, который не уходит.
|
||||||
|
|
||||||
### Airflow Overview
|
### Airflow Overview
|
||||||
|
|
||||||
@@ -187,7 +196,7 @@ URL: `http://localhost:3000/d/airflow-overview/airflow-overview`
|
|||||||
|
|
||||||
### `scrape_configs`: кого опрашивает Prometheus
|
### `scrape_configs`: кого опрашивает Prometheus
|
||||||
|
|
||||||
В файле три блока:
|
В файле четыре блока:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
scrape_configs:
|
scrape_configs:
|
||||||
@@ -202,10 +211,12 @@ scrape_configs:
|
|||||||
`localhost`: Prometheus живёт внутри compose-сети и ходит к соседним контейнерам по их service
|
`localhost`: Prometheus живёт внутри compose-сети и ходит к соседним контейнерам по их service
|
||||||
name.
|
name.
|
||||||
|
|
||||||
Kafka и Airflow устроены так же, но с exporter-ами:
|
Kafka, Airflow и generator устроены так же, но источники разные:
|
||||||
|
|
||||||
- `kafka` → `kafka-exporter:9308`;
|
- `kafka` → `kafka-exporter:9308`;
|
||||||
- `airflow` → `statsd-exporter:9102`.
|
- `airflow` → `statsd-exporter:9102`;
|
||||||
|
- `generator` → `generator:9109`, только когда live-генератор явно запущен.
|
||||||
|
Без live этот target может быть `DOWN`, как в проверке Prometheus выше.
|
||||||
|
|
||||||
### Почему Airflow идёт через StatsD
|
### Почему Airflow идёт через StatsD
|
||||||
|
|
||||||
@@ -257,9 +268,21 @@ Grafana.
|
|||||||
| Airflow Alerts | `High Task Failure Rate` | растёт rate failed tasks |
|
| Airflow Alerts | `High Task Failure Rate` | растёт rate failed tasks |
|
||||||
| Airflow Alerts | `High DAG Parse Time` | DAG-файлы долго парсятся |
|
| Airflow Alerts | `High DAG Parse Time` | DAG-файлы долго парсятся |
|
||||||
|
|
||||||
Не все эти правила обязаны стрелять в учебном стенде. Часть порогов специально похожа на
|
Не все эти правила обязаны быть тихими в учебном стенде. По умолчанию `make up` и
|
||||||
продовые: они показывают, как формулируется условие, но не создают шум на каждом маленьком
|
`make generated-history-analytics` **не запускают live-генератор**, поэтому после готовой
|
||||||
прогоне.
|
стартовой истории новые сообщения перестают приходить. Из-за этого `Kafka No Messages Produced`
|
||||||
|
может перейти в `Alerting` на полностью здоровом backfill-only стенде. Если хочешь проверить
|
||||||
|
это правило в спокойном состоянии, явно включи live:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make generator-continue
|
||||||
|
```
|
||||||
|
|
||||||
|
После наблюдения останови live-генератор, чтобы он не менял стенд дальше:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make generator-down
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -334,7 +357,7 @@ make recover-monitoring
|
|||||||
|
|
||||||
| Действие | Где смотреть | Что ожидать |
|
| Действие | Где смотреть | Что ожидать |
|
||||||
|----------|--------------|-------------|
|
|----------|--------------|-------------|
|
||||||
| открыть Prometheus targets | `http://localhost:9090` → Status → Targets | `clickhouse`, `kafka`, `airflow` в состоянии `UP` |
|
| открыть Prometheus targets | `http://localhost:9090` → Status → Targets | `clickhouse`, `kafka`, `airflow` в состоянии `UP`; `generator` может быть `DOWN` без live |
|
||||||
| открыть `ClickHouse Overview` | Grafana dashboards | панели `Queries per Second`, `Failed Queries (total)`, `Inserted Rows/sec` не пустые |
|
| открыть `ClickHouse Overview` | Grafana dashboards | панели `Queries per Second`, `Failed Queries (total)`, `Inserted Rows/sec` не пустые |
|
||||||
| открыть `Kafka Overview` | Grafana dashboards | видны `Brokers Up`, `Topics`, `Consumer Lag by Group` |
|
| открыть `Kafka Overview` | Grafana dashboards | видны `Brokers Up`, `Topics`, `Consumer Lag by Group` |
|
||||||
| открыть `Airflow Overview` | Grafana dashboards | видны `Scheduler Heartbeat Rate`, `Queued Tasks`, `Task Failures vs Success Rate` |
|
| открыть `Airflow Overview` | Grafana dashboards | видны `Scheduler Heartbeat Rate`, `Queued Tasks`, `Task Failures vs Success Rate` |
|
||||||
|
|||||||
Reference in New Issue
Block a user