Django 测试:如何在 SQLite 上测试并发用户?

Posted

技术标签:

【中文标题】Django 测试:如何在 SQLite 上测试并发用户?【英文标题】:Django tests: how to test concurrent users on SQLite? 【发布时间】:2014-12-20 15:23:12 【问题描述】:

我的 Django webapps 是多人策略游戏,其中涉及玩家浏览一系列页面并在每个页面上提交一个 ModelForm。它们通常是来回游戏,因此玩家 1 做出决定,而玩家 2 看到等待屏幕,反之亦然,依此类推。游戏可以有可变数量的玩家。

我已经使用 Django 的 HTTP 测试客户端实现了测试,其中测试被设计为从单个用户的角度编写,具有分支的条件逻辑,无论客户端播放为 P1 还是 P2,并且抽象了等待屏幕:

def play(self):

    self.submit(views.Introduction)
    self.submit(views.Question1, 'answer': random.choice([True,False]))

    if self.player.id_in_group == 1:
        self.submit(views.Send, "sent_amount": 4)
    else:
        self.submit(views.SendBack, 'sent_back_amount': 8)

    self.submit(views.Results)
    self.submit(views.Question2, dict(feedback=4))

然后,为了模拟 N 个玩家,我实例化了 N 个线程,每个线程都执行上面的代码。

这种方法适用于 Postgres,但不适用于 SQLite,由于外部原因,SQLite 是我们需要用于本地开发的引擎。我得到:OperationalError: Database is locked

有什么方法可以避免锁吗?像任务队列一样,还是在 SQlite DB 解锁之前一直处于休眠状态?或者以某种方式以随机顺序循环测试客户端并在给定时间从每个客户端执行几行?如果我们在 SQLite 上稍微降低性能也没关系。

注意:我可以内联编写多个播放器的代码,以便它们都在 1 个线程中执行,但是 (1) 我发现该代码更难阅读,(2) 它是人为的,因为它硬编码了动作的确切顺序将被执行,并且 (3) 当我们将 10 人游戏更改为 20 人游戏时,它不能很好地扩展。

【问题讨论】:

docs.djangoproject.com/en/dev/ref/databases/… sqlite 的问题在于它是“精简版”,在并发方面非常有限。我知道您说 sqlite 是必需的,但实际上唯一实际的解决方法是让每个开发人员设置一个本地 postrges 服务器进行开发。这可以使用 vagrant 或 buildout 等工具轻松完成。 OperationalError: database is locked的可能重复 【参考方案1】:

SQLite 支持multi threaded mode。在这种模式下,SQLite 可以被多个线程安全地使用,前提是没有在两个或多个线程中同时使用单个数据库连接。

Celery 提供了一种确保only one task runs at a time 的方法。如果您使用 celery 进行数据库事务,那么 celery 会确保一次只允许一个事务运行,这可以解决您的问题。

【讨论】:

以上是关于Django 测试:如何在 SQLite 上测试并发用户?的主要内容,如果未能解决你的问题,请参考以下文章

“ContentType 匹配查询不存在” - 仅在 SQLite 上,而不是 MySQL

如何在我的生产数据库副本上运行 Django 测试?

如何在使用 SQLite 作为内存数据库的 ABP 框架上集成测试接受 SQL 参数的方法?

heroku 没有名为 _sqlite3 的模块

如何在 Django 中使用不同的设置进行单元测试?

Linux下安装Python3的django并配置mysql作为django默认数据库(转载)