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

1 投票
1 回答
663 浏览
提问于 2025-04-29 12:27

我的Django网页应用是一些多人策略游戏,玩家需要在一系列页面中进行操作,每个页面都要提交一个表单。这些游戏通常是来回进行的,玩家1做出决定时,玩家2则看到一个等待的界面,然后再换过来,依此类推。游戏的玩家人数可以变化。

我使用Django的HTTP测试客户端来实现测试,这些测试是从单个用户的角度来写的,里面有条件逻辑来判断客户端是作为玩家1还是玩家2来进行操作,同时把等待界面给抽象掉了:

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数据库解锁之前让程序休眠?或者以随机顺序循环测试客户端,并在特定时间执行每个客户端的几行代码?在SQLite上稍微降低性能也没关系。

注意:我可以把多个玩家的代码写在一起,这样它们就都在一个线程中执行,但(1)我觉得这样写的代码不太容易读,(2)这样做不太自然,因为它硬编码了一个确切的执行顺序,(3) 当我们把一个10人的游戏改成20人的游戏时,这种方式也不太好扩展。

暂无标签

1 个回答

1

SQLite支持多线程模式。在这个模式下,SQLite可以被多个线程安全地使用,只要没有一个数据库连接在两个或更多线程中同时使用。

Celery提供了一种方法来确保一次只运行一个任务。如果你在数据库操作中使用Celery,那么Celery会确保一次只允许一个操作进行,这样就解决了你的问题。

撰写回答