Как подключиться к Cassandra в приложении Pylons? - PullRequest
10 голосов
/ 09 сентября 2010

Я создал новый проект Pylons и хотел бы использовать Cassandra в качестве сервера базы данных.Я планирую использовать Pycassa, чтобы иметь возможность использовать cassandra 0.7beta.К сожалению, я не знаю, где создать экземпляр подключения, чтобы сделать его доступным в моем приложении.

Цель состоит в том, чтобы:

  • Создать пул при запуске приложения
  • Получить соединение из пула для каждого запроса и сделать его доступным длямои контроллеры и библиотеки (в контексте запроса).Лучше всего было бы получить соединение из пула «лениво», то есть только в случае необходимости
  • Если соединение использовалось, отмените его, когда запрос будет обработан

ДополнительноЕсть ли что-то важное, что я должен знать об этом?Когда я вижу некоторые комментарии, такие как «Будьте осторожны при использовании QueuePool с use_threadlocal = True, особенно с включенными повторными попытками. Может потребоваться синхронизация, чтобы предотвратить изменение соединения, когда его использует другой поток». Что это означает точно?

Спасибо.

- Пьер

Ответы [ 2 ]

2 голосов
/ 10 сентября 2010

Хорошо. Я работал немного больше. На самом деле, использование диспетчера соединений, вероятно, было не очень хорошей идеей, так как этот должен быть контекстом шаблона. Кроме того, открытие соединения для каждого потока не имеет большого значения. Открытие соединения по запросу будет.

Я закончил с pycassa.connect_thread_local() в app_globals, и вот я здесь.

1 голос
/ 09 сентября 2010

Хорошо.Я немного поработал, я многому научился и нашел возможный ответ.

Создание пула

Лучшее место для создания пула - файл app_globals.py, которыйэто в основном контейнер для объектов, которые будут доступны «на протяжении всего жизненного цикла приложения».На самом деле именно то, что я хочу для пула.

Я только что добавил в конец файла свой код инициализации, который берет настройки из файла конфигурации пилонов:

"""Creating an instance of the Pycassa Pool"""
kwargs = {}

# Parsing servers
if 'cassandra.servers' in config['app_conf']:
    servers = config['app_conf']['cassandra.servers'].split(',')
    if len(servers):
        kwargs['server_list'] = servers

# Parsing timeout
if 'cassandra.timeout' in config['app_conf']:
    try:
        kwargs['timeout'] = float(config['app_conf']['cassandra.timeout'])
    except:
        pass

# Finally creating the pool
self.cass_pool = pycassa.QueuePool(keyspace='Keyspace1', **kwargs)

Я мог бысделали лучше, например, переместив это в функцию или поддерживая больше параметров (размер пула, ...).Что я и сделаю.

Получение соединения при каждом запросе

Хорошо.Кажется, есть простой способ: в файле base.py добавить что-то вроде c.conn = g.cass_pool.get() перед вызовом WSGIController, что-то вроде c.conn.return_to_pool() после.Это просто и работает.Но это получает соединение из пула, даже если это не требуется контроллером.Я должен копнуть немного глубже.

Создание диспетчера соединений

У меня была простая идея создать класс, который будет создаваться при каждом запросе в файле base.py и который будетавтоматически захватывать соединение из пула по запросу (и освобождать его после).Это действительно простой класс:

class LocalManager:
    '''Requests a connection from a Pycassa Pool when needed, and releases it at the end of the object's life'''

    def __init__(self, pool):
        '''Class constructor'''
        assert isinstance(pool, Pool)
        self._pool = pool
        self._conn = None

    def get(self):
        '''Grabs a connection from the pool if not already done, and returns it'''
        if self._conn is None:
            self._conn = self._pool.get()
        return self._conn

    def __getattr__(self, key):
        '''It's cooler to write "c.conn" than "c.get()" in the code, isn't it?'''
        if key == 'conn':
            return self.get()
        else:
            return self.__dict__[key]

    def __del__(self):
        '''Releases the connection, if needed'''
        if not self._conn is None:
            self._conn.return_to_pool()

Только что добавил c.cass = CassandraLocalManager(g.cass_pool) перед вызовом WSGIController в base.py, del(c.cass) после, и я все сделал.

И это работает:

conn = c.cass.conn
cf = pycassa.ColumnFamily(conn, 'TestCF')
print cf.get('foo')

\ o /

Я не знаю, является ли это лучшим способом сделать это.Если нет, пожалуйста, дайте мне знать =) Плюс, я все еще не понимал часть «синхронизации» в исходном коде Pycassa.Если это необходимо в моем случае, и что я должен делать, чтобы избежать проблем.

Спасибо.

...