Как исправить проблему «Невозможно завершить операцию с любыми хостами» в Cassandra?

#python #cassandra #nosql #amazon-keyspaces #datastax-python-driver

#python #кассандра #nosql #amazon-keyspaces #datastax-python-driver

Вопрос:

У меня есть довольно простая функция AWS Lambda, с помощью которой я подключаюсь к базе данных Amazon Keyspaces для Cassandra. Этот код на Python работает, но время от времени я получаю сообщение об ошибке. Как мне исправить это странное поведение? У меня есть предположение, что вам нужно внести дополнительные настройки при инициализации кластера. Например, set_max_connections_per_host . Я был бы признателен за любую помощь.

ОШИБКА:

 ('Unable to complete the operation against any hosts', {<Host: X.XXX.XX.XXX:XXXX eu-central-1>: ConnectionShutdown('Connection to X.XXX.XX.XXX:XXXX was closed')})
  

lambda_function.py:

 import sessions


cassandra_db_session = None
cassandra_db_username = 'your-username'
cassandra_db_password = 'your-password'
cassandra_db_endpoints = ['your-endpoint']
cassandra_db_port = 9142


def lambda_handler(event, context):
    global cassandra_db_session
    if not cassandra_db_session:
        cassandra_db_session = sessions.create_cassandra_session(
            cassandra_db_username,
            cassandra_db_password,
            cassandra_db_endpoints,
            cassandra_db_port
        )
    result = cassandra_db_session.execute('select * from "your-keyspace"."your-table";')
    return 'ok'
  

sessions.py:

 from ssl import SSLContext
from ssl import CERT_REQUIRED
from ssl import PROTOCOL_TLSv1_2
from cassandra.cluster import Cluster
from cassandra.auth import PlainTextAuthProvider
from cassandra.policies import DCAwareRoundRobinPolicy


def create_cassandra_session(db_username, db_password, db_endpoints, db_port):
    ssl_context = SSLContext(PROTOCOL_TLSv1_2)
    ssl_context.load_verify_locations('your-path/AmazonRootCA1.pem')
    ssl_context.verify_mode = CERT_REQUIRED
    auth_provider = PlainTextAuthProvider(username=db_username, password=db_password)
    cluster = Cluster(
        db_endpoints,
        ssl_context=ssl_context,
        auth_provider=auth_provider,
        port=db_port,
        load_balancing_policy=DCAwareRoundRobinPolicy(local_dc='eu-central-1'),
        protocol_version=4,
        connect_timeout=60
    )
    session = cluster.connect()
    return session
  

Ответ №1:

Нет особого смысла устанавливать максимальное количество подключений на стороне клиента, поскольку лямбды AWS фактически «мертвы» между запусками. По той же причине рекомендуется отключить сердцебиение драйвера (с idle_heartbeat_interval = 0 помощью ), поскольку до следующего вызова функции не происходит никаких действий.

Это не обязательно вызывает проблему, которую вы видите, но есть большая вероятность, что соединение повторно используется драйвером после его закрытия на стороне сервера.

Из-за отсутствия общедоступной документации по внутренней работе AWS Keyspaces трудно понять, что происходит в кластере. Я всегда подозревал, что AWS Keyspaces имеет CQL-подобный API-движок перед динамической базой данных, поэтому есть такие причуды, как то, что вы видите, которые трудно отследить, поскольку для этого требуются знания, доступные только внутри AWS.

FWIW драйверы DataStax не тестируются на AWS Keyspaces.

Комментарии:

1. Большое вам спасибо за ваши рекомендации. Поскольку каждый раз подключение к базе данных занимает очень много времени, я определил подключение к базе данных вне lambda_handler функции. Соединение с базой данных будет создано при первом вызове функции. Любой последующий вызов функции будет использовать то же соединение с базой данных. Если функция AWS Lambda не используется в течение 15 минут, соединение пропадает. Насколько это правильно, по вашему мнению?

2. Я попробую добавить idle_heartbeat_interval во время инициализации кластера и протестирую его сегодня в течение дня. Я сообщу вам о результатах.

3. Опять же, трудно понять, как AWS Keyspaces обрабатывает соединения, поэтому сложно комментировать. Приветствия!

Ответ №2:

Это самая большая проблема, которую я вижу:

 result = cassandra_db_session.execute('select * from "your-keyspace"."your-table";')
  

Код выглядит нормально, но я не вижу WHERE предложения. Итак, если данных много, один узел (выбранный в качестве координатора) должен будет создать результирующий набор, извлекая данные со всех других узлов. Поскольку это приводит к (не) предсказуемо плохой производительности, это может объяснить, почему иногда это работает, но не другие.

Совет: все запросы в Cassandra должны содержать WHERE предложение.

Комментарии:

1. Привет! В этом сообщении я забыл указать это, но на самом деле я использую WHERE предложение. Что еще может вызвать ранее упомянутую ошибку? Я думаю, мне нужно добавить дополнительные настройки в кластер, но я не знаю, какие именно. Что вы думаете об этом?