CREATE RESOURCE POOL CLASSIFIER

CREATE RESOURCE POOL CLASSIFIER создаёт классификатор пулов ресурсов.

Синтаксис

CREATE RESOURCE POOL CLASSIFIER <name>
WITH ( <parameter_name> [= <parameter_value>] [, ... ] )
  • name — имя создаваемого классификатора пула ресурсов. Должно быть уникальным. Имя не должно содержать символы, запрещённые для схемных объектов.
  • WITH ( <parameter_name> [= <parameter_value>] [, ... ] ) — позволяет задавать значения параметров, определяющих поведение классификатора пула ресурсов.

Общие параметры

  • RANK (Int64) — опциональное поле, задающее порядок выбора классификатора пула ресурсов. Если значение не указано, берётся максимальный существующий RANK и к нему прибавляется 1000. Допустимые значения: уникальное число в диапазоне .
  • RESOURCE_POOL (String) — имя пула ресурсов, в который направляются запросы, удовлетворяющие предикатам классификатора.
  • ACTION (Enum) — действие, применяемое к запросу при срабатывании классификатора. Допустимое значение — reject: запрос отклоняется, пользователь получает ошибку вида Request is rejected by classifier '<name>' (rank=<rank>).

Примечание

Параметры RESOURCE_POOL и ACTION взаимоисключающие: в классификаторе должен быть указан ровно один из них.

Параметры-предикаты

Предикат — условие, проверяемое для входящего запроса. Классификатор срабатывает, если выполнены все его предикаты (логическое AND). Для реализации логики OR необходимо создать несколько классификаторов с разными значениями RANK. Классификаторы обрабатываются в порядке возрастания RANK; обработка останавливается на первом сработавшем — к запросу применяется его ACTION или он направляется в его RESOURCE_POOL.

Параметры-предикаты необязательны. Классификатор без предикатов срабатывает на любой запрос — это удобно для «закрывающего» классификатора с максимальным RANK, например, направить весь неклассифицированный трафик в конкретный пул (RESOURCE_POOL) или отклонить его (ACTION='reject').

Важно

Будьте внимательны при создании «закрывающего» классификатора: все классификаторы, следующие за ним по RANK, никогда не сработают — обработка останавливается на первом совпадении, а «закрывающий» срабатывает всегда.

Список предикатов:

  • MEMBER_NAME (String) — SID пользователя или группы, от имени которых поступил запрос. Подробнее — ниже.
  • HAS_PATH (String) — путь к объекту YDB, к которому обращается запрос; поддерживает подстановочные знаки * и ?. Подробнее — ниже.
  • HAS_APP_NAME (String) — идентификатор клиентского приложения. Подробнее — ниже.
  • HAS_FULL_SCAN (String) — путь к объекту, по которому ожидается полное сканирование; поддерживает подстановочные знаки * и ?. Подробнее — ниже.
  • HAS_STREAM (Bool) — признак стримингового запроса. Подробнее — ниже.

MEMBER_NAME

MEMBER_NAME сравнивается посимвольно с SID пользователя или любым SID группы из его токена аутентификации. Формат SID зависит от того, каким способом пользователь пришёл в систему.

В качестве значения можно указать как SID конкретного пользователя, так и SID группы. Ко всем аутентифицированным пользователям автоматически добавляется группа all-users@well-known — её удобно использовать, если нужно направить в пул запросы от всех аутентифицированных клиентов.

Пример. Направить запросы пользователя user1@ldap в пул olap:

CREATE RESOURCE POOL CLASSIFIER cl_user WITH (
    RANK=100,
    RESOURCE_POOL='olap',
    MEMBER_NAME='user1@ldap'
);

HAS_PATH

HAS_PATH сравнивает пути объектов YDB, к которым обращается запрос, с указанной маской. Маска поддерживает подстановочные знаки: * — любая последовательность символов, ? — один любой символ. Предикат срабатывает, если хотя бы один объект в плане запроса соответствует маске.

Пример. Направить запросы к архивным таблицам в пул pool_archive:

CREATE RESOURCE POOL CLASSIFIER cl_archive WITH (
    RANK=700,
    RESOURCE_POOL='pool_archive',
    HAS_PATH='/Root/db/archive/*'
);

HAS_APP_NAME

HAS_APP_NAME сравнивает значение с идентификатором клиентского приложения. Значение передаётся клиентом в метаданных gRPC-запроса через заголовок x-ydb-application-name; SDK YDB предоставляют способ задать его на стороне клиента. Сравнение — на точное совпадение (без подстановочных знаков).

Важно

Значение HAS_APP_NAME задаётся клиентом и не аутентифицируется сервером — не используйте его как средство контроля доступа. Для эффективной изоляции сочетайте с MEMBER_NAME или направляйте нераспознанные запросы в sandbox-пул с жёсткими лимитами.

Установка идентификатора приложения в клиенте:

  • YDB UI — фиксированное значение ydb-ui, задаётся YDB UI и не настраивается пользователем.
  • YDB CLI — не поддерживается: идентификатор клиентского приложения в запросе не отправляется.
  • YDB C++ SDK — на каждом запросе через параметр Header настроек TRequestSettings: settings.Header({{ NYdb::YDB_APPLICATION_NAME, "my-app" }}), где константа YDB_APPLICATION_NAME равна x-ydb-application-name.
  • YDB Go SDK — на драйвере через опцию WithApplicationName в вызове ydb.Open.
  • YDB Java SDK — на транспорте через метод GrpcTransportBuilder.withApplicationName.
  • YDB Python SDK — отдельного параметра нет; значение задаётся на каждом запросе через дополнительный заголовок: settings.with_header("x-ydb-application-name", "my-app") (метод BaseRequestSettings.with_header).

Пример. Направить запросы от YDB UI в пул pool_adhoc:

CREATE RESOURCE POOL CLASSIFIER cl_adhoc_ui WITH (
    RANK=200,
    RESOURCE_POOL='pool_adhoc',
    HAS_APP_NAME='ydb-ui'
);

HAS_FULL_SCAN

HAS_FULL_SCAN определяет запросы, содержащие полное сканирование указанных объектов. Полное сканирование — чтение таблицы без ограничения по ключу или диапазону ключей. Аргумент — маска пути к объекту с поддержкой подстановочных знаков * и ?; предикат срабатывает, если в плане запроса есть хотя бы один такой объект. Поддерживаются как строковые, так и колоночные таблицы. Объекты, к которым понятие полного сканирования неприменимо (например, топики), не учитываются.

Особенности определения полного сканирования:

  • LIMIT не отменяет полное сканирование. Без условия по ключу формируется физический план, обрабатывающий всю таблицу целиком; LIMIT ограничивает только размер результата.

  • Вторичные индексы. Полное сканирование индексной таблицы вторичного индекса засчитывается по её собственному пути. Например, у таблицы

    CREATE TABLE orders (
        Id Uint64 NOT NULL,
        Status Utf8,
        PRIMARY KEY (Id),
        INDEX by_status GLOBAL ON (Status)
    );
    

    индексная таблица имеет путь /Root/orders/by_status/indexImplTable. Запрос SELECT * FROM orders VIEW by_status выполняет полное сканирование именно индексной таблицы — основная /Root/orders не сканируется. Поэтому:

    • HAS_FULL_SCAN='/Root/orders' — не сработает;
    • HAS_FULL_SCAN='/Root/orders/by_status/indexImplTable' или HAS_FULL_SCAN='/Root/orders/*' — сработает.

Пример. Отклонять запросы, вызывающие полное сканирование архива заказов:

CREATE RESOURCE POOL CLASSIFIER cl_fullscan_reject WITH (
    RANK=100,
    ACTION='reject',
    HAS_FULL_SCAN='/Root/db/orders_archive/*'
);

HAS_STREAM

HAS_STREAM определяет, является ли запрос стриминговым — то есть выполняет длительное непрерывное чтение и/или запись из потоков данных. Допустимые значения:

  • true — классификатор срабатывает на стриминговых запросах;
  • false — классификатор срабатывает на нестриминговых запросах.

Пример. Направить стриминговые запросы в пул pool_stream:

CREATE RESOURCE POOL CLASSIFIER cl_stream WITH (
    RANK=500,
    RESOURCE_POOL='pool_stream',
    HAS_STREAM=true
);

Замечания

Если в DDL для создания классификатора пула ресурсов не указан RANK, то по умолчанию ему будет присвоено значение . Все значения RANK должны быть уникальными, чтобы обеспечить строго детерминированный порядок выбора пула ресурсов в случае конфликтующих условий. Такое поведение выбрано для возможности добавлять новые классификаторы пулов ресурсов между уже существующими.

Также возможно наличие классификатора, который ссылается на несуществующий пул ресурсов или к которому у пользователя нет доступа. В таком случае он пропускается.

С ограничениями на число классификаторов можно ознакомиться на странице ограничений.

Разрешения

Требуется разрешение USE на базу данных.

Пример выдачи такого разрешения:

GRANT 'USE' ON `/my_db` TO `user1@domain`;

Примеры

Ниже — сводный пример, комбинирующий несколько классификаторов и предикатов: отклонение полных сканов архивных таблиц, изоляция стриминговых запросов и выделение пула под интерактивные запросы админа из YDB UI.

Создание ресурсных пулов:

CREATE RESOURCE POOL pool_stream WITH (
    TOTAL_CPU_LIMIT_PERCENT_PER_NODE=20
);

CREATE RESOURCE POOL pool_adhoc_admin WITH (
    TOTAL_CPU_LIMIT_PERCENT_PER_NODE=10
);

Создание классификаторов:

-- Отклонять полные сканы архивных таблиц.
CREATE RESOURCE POOL CLASSIFIER cl_fullscan_reject WITH (
    RANK=100,
    ACTION='reject',
    HAS_FULL_SCAN='/Root/db/orders_archive/*'
);

-- Стриминговые запросы направлять в выделенный пул.
CREATE RESOURCE POOL CLASSIFIER cl_stream WITH (
    RANK=200,
    RESOURCE_POOL='pool_stream',
    HAS_STREAM=true
);

-- Запросы админа из YDB UI — в пул интерактивных запросов.
-- Условие AND: и MEMBER_NAME, и HAS_APP_NAME должны совпасть.
CREATE RESOURCE POOL CLASSIFIER cl_adhoc_admin WITH (
    RANK=300,
    RESOURCE_POOL='pool_adhoc_admin',
    MEMBER_NAME='admin',
    HAS_APP_NAME='ydb-ui'
);

Классификаторы обрабатываются в порядке возрастания RANK; для запроса срабатывает первый подходящий. Запрос, не удовлетворяющий ни одному классификатору, направляется в пул default.

См. также

Предыдущая
Следующая