如何在Pylons应用程序中连接到Cassandra?

时间:2010-09-08 20:14:55

标签: python pylons cassandra

我创建了一个新的Pylons项目,并希望使用Cassandra作为我的数据库服务器。我打算使用Pycassa来使用cassandra 0.7beta。 不幸的是,我不知道在哪里实例化连接以使其在我的应用程序中可用。

目标是:

  • 启动应用程序时创建池
  • 为每个请求从池中获取连接,并将其提供给我的控制器和库(在请求的上下文中)。最好的方法是“懒洋洋地”从泳池中获取连接,即仅在需要时
  • 如果已使用连接,请在处理请求时将其释放

此外,我应该知道一些重要事项吗?当我看到一些评论时,“使用带有use_threadlocal = True的QueuePool时要小心,特别是启用了重试。可能需要同步以防止连接在另一个线程正在使用时发生变化。”,这究竟是什么意思?

感谢。

- 皮尔

2 个答案:

答案 0 :(得分:2)

好。我工作了一点。实际上,使用连接管理器可能不是一个好主意,因为应该是模板上下文。此外,为每个线程打开一个连接并不是什么大问题。每个请求打开一个连接将是。

我最终在app_globals中只有pycassa.connect_thread_local(),我就去了。

答案 1 :(得分:1)

好。 我工作了一点,我学到了很多,我找到了一个可能的答案。

创建池

创建池的最佳位置似乎位于app_globals.py文件中,该文件基本上是对象的容器,可以在“应用程序的整个生命周期”中访问。事实上,正是我想要一个游泳池。

我刚刚在文件的末尾添加了我的初始化代码,它从pylons配置文件中获取设置:

"""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)base.py之后调用WSGIController之前添加了del(c.cass),我已经完成了。

它有效:

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

\ O /

我不知道这是否是最好的方法。如果没有,请让我知道=) 另外,我仍然不理解Pycassa源代码中的“同步”部分。如果在我的情况下需要它,我该怎么做才能避免问题。

感谢。