scribble

ottocho's blog

Home About GitHub

25 Mar 2014
Peewee reconnect

peewee reconnect

前言

peewee 的 mysql 连接使用的是 MySQLdb。在使用了 peewee 的 app 会出现这么一个问题:没有持续的访问量的、又需要持续提供服务的后台 app,在一段时间后会出现 MySQL has gone away 的问题。这是因为 peewee 中的 MySQL 连接断开了。

python MySQLdb 库没有提供方法检查连接的情况,也没有提供自动重连的方式。

因此,在应用场景中需要对 peewee 中的 MySQL 的连接对象加上一个定时重连:在一定时间段内,主动 reconnect python 中的 MySQL 连接。

此方法抄袭自 torndb

timeout reconnect

peewee 的 Database 类用以配置 peewee 的 model 对象的数据库信息、以及维持连接、进行具体的数据库操作。

因此首先需要修改的是 Database.__init__

def __init__(self, database, threadlocals=False, autocommit=True,
             max_idle_time=3*3600,
             fields=None, ops=None, **connect_kwargs):
    self.init(database, **connect_kwargs)

    if threadlocals:
        self.__local = threading.local()
    else:
        self.__local = type('DummyLocal', (object,), {})

    # XXX added by ottocho
    # Mysql by default closes client connections that are idle for
    # 8 hours, but the client library does not report this fact until
    # you try to perform a query and it fails.  Protect against this
    # case by preemptively closing and reopening the connection
    # if it has been idle for too long (3 hours by default).
    self.__local.last_use_time = time.time()
    self.max_idle_time = max_idle_time

    self._conn_lock = threading.Lock()
    self.autocommit = autocommit

last_use_time 用以当前连接最后一次使用的时间,max_idle_time 用以指定连接最长空闲时间,如果空闲超过 max_idle_time,则此连接需要重连。

因此,修改了 Databaseget_conn 函数:

def get_conn(self):
    if not hasattr(self.__local, 'closed') or self.__local.closed:
        # 如果没有连接过、或者已经被关闭了,则进行连接
        self.connect()
    elif (time.time() - self.__local.last_use_time > self.max_idle_time):
        # 如果超时了 那就重连
        self.reconnect()
    self.__local.last_use_time = time.time()
    return self.__local.conn

再加上 reconnect 函数的实现、和一些调试,此项工作就完成了。

后记

ottocho

2014.04.15


Til next time,
at 20:23

scribble

Home About GitHub