Хорошо.Я немного поработал, я многому научился и нашел возможный ответ.
Создание пула
Лучшее место для создания пула - файл 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.Если это необходимо в моем случае, и что я должен делать, чтобы избежать проблем.
Спасибо.