本文介绍了Django会话竞赛条件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

摘要:Django会话中是否存在竞争条件,如何防止这种情况发生?

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

I have an interesting problem with Django sessions which I think involves a race condition due to simultaneous requests by the same user.

它发生在脚本中,用于同时上传多个文件,并在localhost上进行了测试.我认为这很可能会导致来自同一用户的同时请求(由于本地主机而导致的响应时间很短,由于文件上传而导致了较长的请求时间).但是,对于本地主机以外的普通请求仍然可能,但是可能性很小.

It has occured in a script for uploading several files at the same time, being tested on localhost. I think this makes simultaneous requests from the same user quite likely (low response times due to localhost, long requests due to file uploads). It's still possible for normal requests outside localhost though, just less likely.

我正在发送几个我认为可以执行的请求(文件发布):

I am sending several (file post) requests that I think do this:

  1. Django自动检索用户的会话*
  2. 不相关的代码需要一些时间
  3. 获取request.session['files'](字典)
  4. 将有关当前文件的数据追加到字典中
  5. 再次将字典存储在request.session['files']
  6. 检查它是否确实已存储
  7. 更多不相关的代码,需要花费时间
  8. Django自动存储用户的会话
  1. Django automatically retrieves the user's session*
  2. Unrelated code that takes some time
  3. Get request.session['files'] (a dictionary)
  4. Append data about the current file to the dictionary
  5. Store the dictionary in request.session['files'] again
  6. Check that it has indeed been stored
  7. More unrelated code that takes time
  8. Django automatically stores the user's session

此处的6处的检查将指示该信息确实已存储在会话中.但是,将来的请求表明有时会,有时甚至没有.

Here the check at 6. will indicate that the information has indeed been stored in the session. However, future requests indicate that sometimes it has, sometimes it has not.

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

What I think is happening is that two of these requests (A and B) happen simultaneously. Request A retrieves request.session['files'] first, then B does the same, changes it and stores it. When A finally finishes, it overwrites the session changes by B.

两个问题:

  1. 这确实是正在发生的事情吗? django开发服务器是多线程的吗?在Google上,我找到有关使其成为多线程的页面,这表明默认情况下不是吗?否则,可能是什么问题?
  2. 如果这种种族状况是问题所在,那么解决该问题的最佳方法是什么?这是一种不便,但不是安全问题,因此,如果可以将机会大大减少,我已经很高兴了.

我认为,在更改之前立即获取会话数据,并在更改之后立即将其保存应该会大大降低机会.但是,我还没有找到一种对request.session进行此操作的方法,只能使用django.contrib.sessions.backends.db.SessionStore解决它.但是我认为,如果以这种方式进行更改,则Django将在请求结束时使用request.session覆盖它.

Retrieving the session data right before the changes and saving it right after should decrease the chance significantly I think. However I have not found a way to do this for the request.session, only working around it using django.contrib.sessions.backends.db.SessionStore. However I figure that if I change it that way, Django will just overwrite it with request.session at the end of the request.

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

So I need a request.session.reload() and request.session.commit(), basically.

推荐答案

  1. 是的,一个请求有可能在另一个请求完成之前开始.您可以通过在视图的开始和结束处打印一些内容来进行检查,并同时启动一堆请求.

  1. Yes, it is possible for a request to start before another has finished. You can check this by printing something at the start and end of a view and launch a bunch of request at the same time.

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

Indeed the session is loaded before the view and saved after the view. You can reload the session using request.session = engine.SessionStore(session_key) and save it using request.session.save().

但是,重新加载会话确实会丢弃在此之前(在视图中或之前)添加到会话中的所有数据.在重新加载之前进行保存会破坏加载点.更好的方法是将文件作为新模型保存到数据库中.

Reloading the session however does discard any data added to the session before that (in the view or before it). Saving before reloading would destroy the point of loading late. A better way would be to save the files to the database as a new model.

答案的实质是在对Thomas答案的讨论中,这是不完整的,因此我已经发布了完整的答案.

这篇关于Django会话竞赛条件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 17:22