Django会话竞争条件?

Mar*_*ark 6 python django session multithreading race-condition

总结:Django会话中是否存在竞争条件,如何防止它?

我对Django会话有一个有趣的问题,我认为由于同一用户的同时请求而涉及竞争条件.

它出现在一个脚本中,用于同时上传多个文件,在localhost上进行测试.我认为这很可能同时发生来自同一用户的请求(由于本地主机的响应时间很短,因文件上传而导致请求时间过长).尽管如此,在localhost之外的正常请求仍然可能,但不太可能.

我发送了几个(文件发布)请求,我认为这样做:

  1. Django自动检索用户的会话*
  2. 不相关的代码需要一些时间
  3. 得到request.session['files'](字典)
  4. 将有关当前文件的数据附加到字典中
  5. request.session['files']再次存储字典
  6. 检查它确实已存储
  7. 更多不相关的代码需要时间
  8. Django自动存储用户的会话

这里的检查将指示信息确实已存储在会话中.但是,未来的请求表明有时它有,有时它没有.

我认为正在发生的是这些请求中的两个(A和B)同时发生.请求A request.session['files']首先检索,然后B执行相同的操作,更改并存储它.当A终于完成时,它会用B覆盖会话更改.

两个问题:

  1. 这确实是发生了什么?django开发服务器是多线程的吗?在Google上,我发现有关使其成为多线程的网页,建议默认情况下不是这样吗?否则,可能是什么问题?
  2. 如果这种竞争条件是问题,那么解决它的最佳方法是什么?这是一个不便,但不是安全问题,所以如果机会可以显着减少,我已经很高兴.

在更改之前检索会话数据并立即保存它应该会减少我认为的机会.但是我还没有找到办法做到这一点request.session,只能使用它来解决它django.contrib.sessions.backends.db.SessionStore.但是我认为如果我改变它,那么Django将request.session在请求结束时覆盖它.

所以我需要一个request.session.reload()request.session.commit(),基本上是这样.

Mar*_*ark 5

  1. 是的,请求可以在另一个请求完成之前启动.您可以通过在视图的开头和结尾打印一些内容来检查这一点,并同时启动一堆请求.

  2. 实际上,会话在视图之前加载并在视图之后保存.您可以使用重新加载会话request.session = engine.SessionStore(session_key)并使用保存request.session.save().

但是重新加载会话会丢弃之前添加到会话中的任何数据(在视图中或之前).在重新加载之前保存会延迟加载点.更好的方法是将文件作为新模型保存到数据库.

答案的实质在于托马斯答案的讨论,这个答案是不完整的,所以我发表了完整的答案.