У меня есть скрипт, который выполняет оператор приема с определенным периодом. В упрощенном виде это выглядит следующим образом:
import time
from azure.kusto.data import KustoClient, KustoConnectionStringBuilder, ClientRequestProperties
cluster = "https://<adxname>.centralus.kusto.windows.net"
client_id = "<sp_guid>"
client_secret = "<sp_secret>"
authority_id = "<tenant_guid>"
db = "db-name"
kcsb = KustoConnectionStringBuilder.with_aad_application_key_authentication(
cluster, client_id, client_secret, authority_id)
client = KustoClient(kcsb)
query = """
.append my_table <|
another_table | where ... | summarize ... | project ...
"""
while True:
client.execute(db, query)
time.sleep(30.0)
Таким образом, он выполняет небольшой запрос каждые 30 секунд. Запрос занимает всего миллисекунды для завершения. Библиотечная версия: azure-kusto-data==3.1.0
.
Некоторое время работает нормально, но через какое-то время начинает глючить с этой ошибкой:
requests.exceptions.HTTPError: 429 Client Error: TooManyRequests for url: https://adxname.centralus.kusto.windows.net/v1/rest/mgmt
azure.kusto.data.exceptions.KustoApiError: The control command was aborted due to throttling. Retrying after some backoff might succeed. CommandType: 'TableAppend', Capacity: 1, Origin: 'CapacityPolicy/Ingestion'.
Глядя на упоминаемую в ошибке CapacityPolicy/Ingestion, я не понимаю, как это может быть актуально. Эта политика оставлена по умолчанию:
.show cluster policy capacity
"Policy": {
"IngestionCapacity": {
"ClusterMaximumConcurrentOperations": 512,
"CoreUtilizationCoefficient": 0.75
},
...
}
Я не совсем понимаю, как это может быть связано с одновременными операциями или использованием ядра, поскольку прием происходит быстро и редко выполняется.
Как устранить проблему?
Судя по сообщению об ошибке, емкость приема для вашего кластера равна 1. Это, вероятно, указывает на то, что вы используете номер SKU для разработчиков, который имеет один узел с 2 ядрами.
При такой настройке в данный момент времени может выполняться только одна операция приема. Любые дополнительные одновременные приемы будут регулироваться.
Вы можете либо реализовать более строгий контроль над клиентами, загружающими данные в кластер, чтобы не более одной команды загрузки пытались выполняться одновременно, а вызывающий код мог восстанавливаться после ошибок регулирования; или масштабируйте кластер вверх/вниз — добавляя больше узлов/ядер, вы увеличиваете пропускную способность.
Вы также можете проверить, кто/что еще принимает данные в ваш кластер, используя .show commands
Предполагая, что у вас есть разрешение на мониторинг или администрирование базы данных, вы можете запустить следующее, чтобы увидеть активность приема за любой заданный период времени (убедитесь, что у вас есть все типы в предложении «in»), например:
.show commands
| where StartedOn > ago(1h)
| where CommandType in ("DataIngestPull", "TableAppend", "TableSetOrReplace", "TableSetOrAppend")
| summarize count() by CommandType
В качестве примечания: для этого типа операций вам следует рассмотреть возможность использования материализованные представления.
Мне нужно зарегистрировать какое-то историческое состояние, скажем, max() с определенной отметкой времени, а затем запросить его. Не могли бы вы описать, как матовые представления могут помочь в этом случае?
Единственный другой прием — это потоковая передача из концентратора событий, которая непредсказуема. Похоже, что повторная попытка клиента - единственный вариант для SKU разработчика...