一位同事想出了一个对我们的用例来说似乎足够好的想法,所以在这里分享一下。基本思想是,您预先创建要使用的 memcache 客户端数量,将它们放入队列中,当您需要 memcache 客户端时,您从队列中拉出一个。由于 Queue.Queue get() 方法具有可选的超时参数,您还可以处理无法及时获取客户端的情况。您还需要处理 memcache 客户端中 threading.local 的使用。
以下是它在代码中的工作方式(请注意,我实际上并没有运行这个确切的版本,所以可能存在一些问题,但是如果文本描述对您没有意义,这应该让您知道):
import Queue
import memcache
# See http://stackoverflow.com/questions/9539052/python-dynamically-changing-base-classes-at-runtime-how-to
# Don't inherit client from threading.local so that we can reuse clients in
# different threads
memcache.Client = type('Client', (object,), dict(memcache.Client.__dict__))
# Client.__init__ references local, so need to replace that, too
class Local(object): pass
memcache.local = Local
class PoolClient(object):
'''Pool of memcache clients that has the same API as memcache.Client'''
def __init__(self, pool_size, pool_timeout, *args, **kwargs):
self.pool_timeout = pool_timeout
self.queue = Queue.Queue()
for _i in range(pool_size):
self.queue.put(memcache.Client(*args, **kwargs))
def __getattr__(self, name):
return lambda *args, **kw: self._call_client_method(name, *args, **kw)
def _call_client_method(self, name, *args, **kwargs):
try:
client = self.queue.get(timeout=self.pool_timeout)
except Queue.Empty:
return
try:
return getattr(client, name)(*args, **kwargs)
finally:
self.queue.put(client)