fix(monitoring): доводы приведены к замерам, пары нод больше не расходятся
- Зачем:
- второй круг ревью нашёл, что текст спорит с собственной приёмкой: окно
держалось доводом «слияния за минуту-две», а замер даёт двадцать секунд;
довод панели ошибок опирался на отказ по памяти, которого ADR 0004 на этом
стенде не обещает.
- Что:
- «Части» сортируются по таблице: сортировка по числу частей разводила две
ноды одной таблицы, как только между ними вставала чужая.
- у «Слияний» столбик шириной в минуту, иначе редкие события выходили
волосяной линией; из заголовка убран «слой» — фильтр отсекает журналы
сервера, а не выбирает слои.
- в cluster.md исправлены довод за окно, ложное «времени в system.parts нет»,
счёт панелей без нод (их две, не одна) и разрешение, в котором снят замер
процессора.
- панель ошибок и её запись в ADR 0002 переписаны под проверенное: отказ на
шарде воспроизведён принудительным пределом памяти.
- из queries.md убран абзац про SELECT 1 — он объяснял пол удалённой панели.
- Проверка:
- make config-test; make smoke 21/21; make check-clickhouse 10/10.
- все десять панелей отвечают через /api/ds/query в окнах на полчаса, час и
шесть часов; шаг столбика слияний проверен отдельным запросом.
This commit is contained in:
1 parent
42075ff9fb
commit
48bec014cf
4 files changed
+66
-43
No files matched your search
@@ -133,8 +133,11 @@ keeper, и обе ноды читают её целиком — запрос в
|
||||
посетителям продиктован [ADR 0007](0007-clickhouse-access.md): своя учётка
|
||||
Grafana заведена там ровно затем, чтобы её запросы были отличимы от
|
||||
человеческих.
|
||||
Отдельная панель ошибок понадобилась под здешний же сюжет про тяжёлый
|
||||
`GROUP BY`: отказ по памяти случается на шарде, и текст ошибки — единственное
|
||||
место, где написано, на каком. Устройство обоих дашбордов —
|
||||
Отдельная панель ошибок понадобилась потому, что отказ достаётся шарду: в
|
||||
замере с принудительным пределом памяти каждая нода записала свой, и строка
|
||||
шарда видна только без фильтра по инициатору. Здешний сюжет про тяжёлый
|
||||
`GROUP BY` при этом кончается не отказом, а сбросом на диск
|
||||
([ADR 0004](0004-resource-limits.md)) — отказ на стенде приходится вызывать
|
||||
настройкой. Устройство обоих дашбордов —
|
||||
[cluster.md](../architecture/monitoring/cluster.md) и
|
||||
[queries.md](../architecture/monitoring/queries.md).
|
||||
@@ -17,14 +17,17 @@
|
||||
| Keeper | встроенные метрики keeper через Prometheus |
|
||||
| Распределённый DDL | `system.distributed_ddl_queue` |
|
||||
|
||||
Окно у дашборда — полчаса, обновление — полминуты, и это выбрано под нагрузку.
|
||||
Вставка на стенде занимает секунды, а слияния разбирают её следы за минуту-две;
|
||||
в часовом окне и подъём, и оседание схлопнулись бы в один столбик. Урок здесь —
|
||||
форма кривой, и окно подобрано так, чтобы форма была видна.
|
||||
Окно у дашборда — полчаса, обновление — полминуты. Пачка из
|
||||
`make generate-batch` проходит за двадцать секунд, и на получасовой оси это
|
||||
узкий всплеск в пару столбиков. Шире окно не берут, чтобы всплеск не выродился
|
||||
в точку; уже — чтобы не промахнуться мимо него, заглянув через минуту, и чтобы
|
||||
рядом осталось спокойное время: подъём читается только над полом. Кто хочет
|
||||
разглядеть форму вплотную, растягивает окно мышью по самому всплеску.
|
||||
|
||||
Две панели окна не знают, и обе по делу. «Части» показывают состояние сейчас:
|
||||
`system.parts` — опись живых частей, времени в ней нет вовсе. Очередь DDL
|
||||
показывает последние двадцать записей: в спокойные полчаса она пуста, а пустая
|
||||
Панель частей окна не знает вовсе. `system.parts` — опись живых частей, и
|
||||
вопрос к ней про сейчас: колонки со временем в ней есть, но ни одна не годится
|
||||
в ось. Очередь DDL окна тоже не знает, но по другой причине: она показывает
|
||||
последние двадцать записей, потому что в спокойные полчаса пуста, а пустая
|
||||
панель ничего бы не рассказала.
|
||||
|
||||
## Обе ноды на одной панели
|
||||
@@ -35,11 +38,15 @@
|
||||
Поэтому запросы идут через `clusterAllReplicas`, а `hostName()` подписывает,
|
||||
чья это строка.
|
||||
|
||||
Исключение одно — очередь распределённых DDL. Она лежит не у ноды, а в keeper,
|
||||
и обе ноды читают из него одну и ту же очередь целиком, вместе со строками про
|
||||
соседа. Обёртка здесь не добавила бы правды, а удвоила бы каждую строку.
|
||||
Правило поэтому звучит так: `clusterAllReplicas` нужен там, где у каждой ноды
|
||||
своя правда.
|
||||
Исключений два, и они разной природы. Очередь распределённых DDL лежит не у
|
||||
ноды, а в keeper, и обе ноды читают из него одну и ту же очередь целиком,
|
||||
вместе со строками про соседа. Обёртка здесь не добавила бы правды, а удвоила
|
||||
бы каждую строку — это единственная панель дашборда без неё. Правило поэтому
|
||||
звучит так: `clusterAllReplicas` нужен там, где у каждой ноды своя правда.
|
||||
|
||||
Второе исключение мягче. Панель слияний читает обе ноды той же обёрткой, но
|
||||
складывает их в один ряд: шарды сливают симметрично, и разделение удвоило бы
|
||||
легенду ради двух одинаковых кривых.
|
||||
|
||||
## Пол на графиках — журналы самого сервера
|
||||
|
||||
@@ -53,16 +60,22 @@ ClickHouse ведёт около десятка собственных журн
|
||||
двух панелях читается как подъём над полом, а не как число само по себе.
|
||||
|
||||
У частей и слияний пол отделим: в `system.parts` и `system.part_log` у каждой
|
||||
строки написано, какой таблице она принадлежит. Обе панели поэтому спрашивают
|
||||
только про слои стенда. Довод в размере: за спокойные полчаса слияния съели
|
||||
строки написано, какой таблице она принадлежит. Обе панели поэтому показывают
|
||||
всё, кроме журналов сервера, — и у каждой на это своя причина.
|
||||
|
||||
Столбик у слияний шириной в минуту, а не в шаг панели. Слияния — события
|
||||
редкие: на своём шаге столбик выродился бы в волосяную линию, и четыре события
|
||||
за полчаса пришлось бы искать глазами.
|
||||
|
||||
Слияниям фильтр иначе не пережить по размеру: за спокойные полчаса они съели
|
||||
6 492 части в системных журналах против 219 в `ods` и `stg` вместе. Оставь мы
|
||||
журналы в кадре, ряды слоёв прижались бы к нулю, и панель рассказывала бы про
|
||||
уборку за сервером вместо ваших вставок. Сколько эта уборка стоит, видно этажом
|
||||
выше, на процессоре и дисках.
|
||||
уборку за сервером вместо приехавших данных. Сколько эта уборка стоит, видно
|
||||
этажом выше, на процессоре и дисках.
|
||||
|
||||
Слияния показаны по слоям, а не по нодам и не по таблицам. Шарды сливают
|
||||
симметрично, и второй ряд на слой удвоил бы легенду, ничего не добавив. Какая
|
||||
именно таблица держит части, отвечает соседняя панель.
|
||||
Частям фильтр нужен для другого: без него в таблице десятки строк, а значит
|
||||
нужен предел — и предел рвёт пару нод пополам, оставляя таблицу с одной нодой в
|
||||
кадре. С фильтром помещаются все, и предел не нужен.
|
||||
|
||||
## Что именно меряют процессор, память и диски
|
||||
|
||||
@@ -109,23 +122,27 @@ Keeper — отдельный сервис, системных таблиц у
|
||||
|
||||
- Дашборд поднимается из каталога сам, все семь панелей отвечают через
|
||||
`/api/ds/query` в окне на полчаса. Пустых нет.
|
||||
- Обе ноды видны на всех панелях по системным таблицам, кроме одной. Без
|
||||
`clusterAllReplicas` осталась очередь DDL, и обёртка ей действительно не
|
||||
нужна: запрос с ней вернул 124 записи с `clickhouse-01` и те же 124 с
|
||||
`clickhouse-02`.
|
||||
- Под нагрузкой. `make generate-batch` (50 626 событий одной пачкой): процессор
|
||||
поднялся с 0,04–0,18 ядра до 0,54 и 0,64, запись — с 400 КиБ/с до 2,1 и
|
||||
4,5 МиБ/с. Следующие десять секунд обе величины уже вернулись к прежним: на
|
||||
таком объёме подъём и оседание укладываются в полминуты.
|
||||
- Слияния под той же нагрузкой отозвались столбиком: два слияния в `stg`,
|
||||
- Обе ноды видны на четырёх панелях из пяти, что читают системные таблицы нод.
|
||||
Пятая — слияния, там ноды сложены намеренно. Без `clusterAllReplicas`
|
||||
осталась только очередь DDL, и обёртка ей действительно не нужна: запрос с
|
||||
ней вернул с `clickhouse-01` и с `clickhouse-02` одно и то же число записей —
|
||||
на день замера 124 и 124.
|
||||
- Под нагрузкой. `make generate-batch` (50 626 событий одной пачкой), замер в
|
||||
десятисекундных вёдрах: процессор поднялся с 0,04–0,18 ядра до 0,54 на одной
|
||||
ноде и 0,64 на другой, запись — с 400 КиБ/с до 2,1 и 4,5 МиБ/с. Ведро тут
|
||||
часть ответа: в тридцатисекундном тот же прогон даёт 0,29 и 0,21 ядра.
|
||||
Следующие десять секунд обе величины уже вернулись к прежним: на таком объёме
|
||||
подъём и оседание укладываются в полминуты.
|
||||
- Слияния под той же нагрузкой отозвались столбиком в ряду `stg` высотой в
|
||||
15 съеденных частей.
|
||||
- Блочное чтение действительно молчит: за минуту вокруг вставки `OSReadBytes`
|
||||
был нулевым в десяти десятисекундных окнах из четырнадцати, а обращения к
|
||||
файлам шли непрерывно во всех.
|
||||
- Память: около 1 ГиБ занятого против 4 ГиБ отведённого на каждой ноде.
|
||||
- Панель частей показала `ods.order_rep` по 142 строки в части против 13 046 у
|
||||
`ods.event_rep` — заказы приезжают дневным слепком, события потоком. Все
|
||||
таблицы слоёв поместились целиком, каждая обеими нодами: восемь строк.
|
||||
`ods.event_rep` — заказы приезжают дневным слепком, события потоком. Строк
|
||||
вышло восемь: четыре таблицы, каждая обеими нодами. Таблиц ошибок среди них
|
||||
нет, и это правда состояния — частей у них пока не появилось.
|
||||
- Очередь DDL показала `CREATE MATERIALIZED VIEW ... ON CLUSTER` в состоянии
|
||||
`Finished` и со временем по каждой ноде: `make generate-batch` поднимает
|
||||
`clickhouse-init`, и тот заново прогоняет DDL.
|
||||
|
||||
@@ -27,10 +27,6 @@ Grafana ходит в ClickHouse обычным пользователем, и
|
||||
остальное. Спрячь мы свои запросы фильтром — цена ушла бы с глаз, а панель «Кто
|
||||
спрашивает» недосчиталась бы самого частого посетителя.
|
||||
|
||||
Там же, в «Кто спрашивает», стоит `default` с сотнями запросов и одной
|
||||
прочитанной строкой на каждый: это `SELECT 1` от проверки состояния
|
||||
контейнера, она ходит к каждой ноде раз в несколько секунд.
|
||||
|
||||
Различать посетителей дашборд умеет потому, что у Grafana своя учётка со своей
|
||||
ролью ([ADR 0007](../../adr/0007-clickhouse-access.md)). Ходи она под
|
||||
аналитиком, панель «Кто спрашивает» показывала бы одну строку на всех.
|
||||
@@ -46,9 +42,11 @@ Grafana ходит в ClickHouse обычным пользователем, и
|
||||
считают только запросы инициатора: иначе один запрос человека выглядел бы
|
||||
тремя, а прочитанные строки сложились бы дважды.
|
||||
|
||||
Панель ошибок, наоборот, куски шардов показывает. Отказ по памяти случается
|
||||
там, где считали, — на шарде; инициатор в своей строке передаст только текст
|
||||
ошибки, а нода, на которой всё случилось, останется неназванной.
|
||||
Панель ошибок, наоборот, куски шардов показывает: отказ случается там, где
|
||||
считали, и строка шарда — единственное место, где эта нода названа. В замере с
|
||||
принудительным пределом памяти `clickhouse-01` записал свой отказ, а
|
||||
`clickhouse-02` — свой, и вторая строка видна только без фильтра по
|
||||
инициатору.
|
||||
|
||||
## Пустой пользователь
|
||||
|
||||
@@ -69,6 +67,10 @@ Grafana ходит в ClickHouse обычным пользователем, и
|
||||
- Ошибки видны и различаются по природе: отказ по правам (`bi` без `SELECT` на
|
||||
`ods`) и ошибка в тексте запроса (несуществующая колонка) легли в панель
|
||||
разными строками, каждая с полным текстом.
|
||||
- Строка шарда в панели ошибок настоящая. Принудительный предел памяти на
|
||||
распределённом `GROUP BY` дал две записи: `clickhouse-01` с
|
||||
`is_initial_query = 1` и `clickhouse-02` с нулём. Вторая пропала бы, стой на
|
||||
панели тот же фильтр, что на соседних.
|
||||
- Панель «Кто спрашивает» разделила шесть учёток — `grafana`, `analyst`, `etl`,
|
||||
`dict`, `bi`, `default` — и фоновую работу сервера. Больше всех прочитала
|
||||
`grafana`: 11,5 млн строк за час, своими же панелями.
|
||||
Reference in new issue
Block a user