3

我正在编写一个基于 web.py 的 Web 服务,使用 Storm 作为 ORM 层从 MySQL 数据库中查询记录。Web 服务是通过 mod_wsgi 在 Linux 机器上使用 Apache2 部署的。create_database()当脚本使用storm的方法启动时,我创建了一个到MySQL数据库服务器的连接。这也是我创建Store对象的地方,该对象稍后用于在请求进入时执行查询。

在几个小时不活动后,store.find()抛出一个DisconnectionError: (2006, 'MySQL server has gone away'). 我并不感到惊讶,因为 Apache/mod_wsgi 重用 Python 进程而没有重新初始化它们很长一段时间,数据库连接被删除。我的问题是如何正确处理这个问题?

我尝试建立一种机制,通过向 MySQL 服务器发送一个重复的“SELECT 1”(每 300 秒)来保持与 MySQL 服务器的连接。不幸的是,这解决了我们的测试机器上的问题,但没有解决我们的演示部署(哎哟),而两者共享相同的 MySQL 配置(wait_timeout设置为 8 小时)。

我已经搜索了将风暴存储重新连接到数据库的解决方案,但没有找到任何复杂的解决方案。唯一的建议似乎是必须捕获异常,将其视为不一致,调用rollback()商店然后重试。但是,这意味着我要么必须包装整个Store类,要么一遍又一遍地实现相同的重试机制。有更好的解决方案还是我在这里完全错了?

更新:我添加了一个 web.py 处理器,如果捕获到异常,则通过重新创建风暴存储来优雅地处理断开连接错误,然后重试 Andrey 推荐的操作。然而,这是一个不完整且次优的解决方案,因为 (a) 存储被少数对象引用以供重用,这需要额外的机制来重新连接每个对象上的存储引用,以及 (b),它不包括在数据库上执行写入时的事务处理(回滚)。但是,至少目前对于 store 上的所有读取操作来说这是一个可以接受的修复。

4

1 回答 1

1

也许您可以使用 web.py 的应用程序处理器来包装您的控制器方法并从中捕获 DisconnectionError。像这样的东西:

def my_processor(handler): 
    tries = 3
    while True:
        try:
            return handler() 
        except DisconnectionError:
            tries -= 1
            if tries == 0:
                raise

或者您可以查看应用程序处理器如何使用 web.py 的 SqlAlchemy 的食谱条目:http ://webpy.org/cookbook/sqlalchemy并为风暴制作类似的内容:

def load_storm(handler):
    web.ctx.store = Store(database)
    try:
        return handler()
    except web.HTTPError:
       web.ctx.store.commit()
       raise
    except:
        web.ctx.store.rollback()
        raise
    finally:
        web.ctx.store.commit()

app.add_processor(load_storm)
于 2012-07-31T11:11:53.870 回答