【发布时间】:2020-08-10 23:10:49
【问题描述】:
我正在与 2 名工人一起使用 Sanic。我正在尝试使计费系统正常工作,即计算用户点击 API 端点的次数。以下是我的代码:
class User(object):
def __init__(self, id, name, age, address, mobile, credits=0):
self.id = id
self.name = name
self.credits = count
self.details = {"age": age, "address": address, "mobile_number": mobile}
上面的用户类用于制作我使用另一个 python 脚本上传到 Redis 的对象,如下所示:
user = User(..., credits = 10)
string_obj = json.dumps(user)
root.set(f"{user.user_id}", string_obj)
当我想维护端点接收的命中数并使用用户对象跟踪它并将其上传回 Redis 时,就会出现主要问题。我的代码如下:
from sanic_redis_ext import RedisExtension
app = Sanic("Testing")
app.config.update(
{
"REDIS_HOST": "127.0.0.1",
"REDIS_PORT": 6379,
"REDIS_DATABASE": 0,
"REDIS_SSL": None,
"REDIS_ENCODING": "utf-8",
"REDIS_MIN_SIZE_POOL": 1,
"REDIS_MAX_SIZE_POOL": 10,
})
@app.route("/test", methods=["POST"])
@inject_user()
@protected()
async def foo(request, user):
user.credits -= 1
if user.credits < 0:
user.credits = 0
return sanic.response.text("Credits Exhausted")
result = process(request)
if not result:
user.credits += 1
await app.redis.set(f"{user.user_id}", json.dumps(user))
return sanic.response.text(result)
这就是我检索用户的方式:
async def retrieve_user(request, *args, **kwargs):
if "user_id" in kwargs:
user_id = kwargs.get("user_id")
else:
if "payload" in kwargs:
payload = kwargs.get("payload")
else:
payload = await request.app.auth.extract_payload(request)
if not payload:
raise exceptions.MissingAuthorizationHeader()
user_id = payload.get("user_id")
user = json.loads(await app.redis.get(user_id))
return user
当我使用 JMeter 以 10 个线程作为同一用户测试 API 端点时,信用系统似乎不起作用。在这种情况下,当用户从 10 个积分开始时,他们最终可能会剩下 7 或 8 个(不可预测)积分,而他们应该还剩下 0 个积分。据我说,这是由于工作人员没有共享用户对象并且没有变量的更新副本,这导致他们覆盖彼此的更新。谁能帮我找到解决方法,这样即使同一个用户同时点击端点,他/她也应该被完美计费,并且应该将用户对象保存回 Redis。
【问题讨论】:
标签: python api redis multiprocessing sanic