【问题标题】:Flask session doesn't update consistently with parallel requestsFlask 会话不会与并行请求一致地更新
【发布时间】:2018-10-15 18:41:38
【问题描述】:

我注意到当并行运行的请求修改 Flask 的 session 时,只记录了一些键。 Flask 的默认 cookie 会话和使用 Redis 后端的 Flask-Session 都会发生这种情况。该项目并不是新项目,但只有在同一会话同时发生许多请求时才会注意到这一点。

import time
from flask import Flask, session
from flask_session import Session

app = Flask(__name__)
app.secret_key = "example"
app.config["SESSION_TYPE"] = "redis"
Session(app)

@app.route("/set/<value>")
def set_value(value):
    """Simulate long running task."""
    time.sleep(1)
    session[value] = "done"
    return "ok\n"

@app.route("/keys")
def keys():
    return str(session.keys()) + "\n"

以下 shell 脚本演示了该问题。请注意,所有请求都已完成,但最终清单中只存在一个键,并且在测试运行之间有所不同。

#!/bin/bash
# set session
curl -c 'cookie' http://localhost:5007/keys
# run parallel
curl -b 'cookie' http://localhost:5007/set/key1 && echo "done1" &
curl -b 'cookie' http://localhost:5007/set/key2 && echo "done2" & 
curl -b 'cookie' http://localhost:5007/set/key3 && echo "done3" &
wait
# get result
curl -b 'cookie' http://localhost:5007/keys
$ sh test.sh 
dict_keys(['_permanent'])
ok
ok
ok
done3
done1
done2
dict_keys(['_permanent', 'key2'])

$ sh test.sh 
dict_keys(['_permanent'])
ok
done3
ok
ok
done2
done1
dict_keys(['_permanent', 'key1'])

为什么请求完成后所有键都不存在?

【问题讨论】:

    标签: python curl flask flask-session


    【解决方案1】:

    基于 Cookie 的会话不是线程安全的。任何给定的请求只能看到随它发送的会话 cookie,并且只返回带有该请求修改的 cookie。这不是 Flask 特有的,它是 HTTP 请求的工作方式。

    您同时发出三个请求。他们都读取了仅包含 _permanent 键的初始 cookie,发送了他们的请求,并获得了一个响应,该响应使用他们的特定键设置了一个 cookie。每个响应 cookie 将只有 _permanent 键和 key_keyN 键。无论哪个请求完成最后一次写入文件,都会覆盖以前的数据,因此您只剩下它的 cookie。

    实际上这不是问题。会话并不真正意味着存储请求之间快速变化的数据,这就是数据库的用途。修改会话的事情(例如登录)不会与同一个会话并行发生(并且无论如何都是幂等的)。

    如果您真的对此感到担忧,请使用服务器端会话将数据存储在数据库中。数据库擅长同步写入。


    您已经在使用 Flask-Session 和 Redis,但深入研究 Flask-Session 实现会发现您遇到此问题的原因。 Flask-Session 不会单独存储每个会话密钥,它会使用所有密钥写入一个序列化值。因此,它遇到了与基于 cookie 的会话相同的问题:只有在该请求期间存在的内容才会被放回 Redis,从而覆盖并行发生的内容。

    在这种情况下,最好编写自己的SessionInterface 子类来单独存储每个键。您将覆盖 save_session 以设置 session 中的所有键并删除任何不存在的键。

    【讨论】:

      猜你喜欢
      • 2017-06-17
      • 2021-12-06
      • 2014-05-13
      • 2017-02-23
      • 2011-10-29
      • 2020-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多