开发:uwsgi开多进程引发的LocMemCache的session冲突
2023.11.18
今天上线了新功能,其中一个具体的实现逻辑如下:
使用 request.session
存储 API 的响应数据,确保会话会偶尔正确地保存并在需要时能够正确地读取数据。
predict.py -- 通过sessions存储all_response_data再重定向对predicted_results页面传递api返回的值
if response_status_code == 200:
all_response_data = []
# ____response____
response_shape_data = response_shape.json()
response_aerobic_data = response_aerobic.json()
response_gram_data = response_gram.json()
all_response_data.append(response_shape_data)
all_response_data.append(response_aerobic_data)
all_response_data.append(response_gram_data)
#print(f'all_response_data: {all_response_data}')
import logging
logger = logging.getLogger('django')
# ______________
logger.error(f'log_all_response_data: {all_response_data}')
if response_shape_data is None:
return HttpResponse('ERROR')
request.session['predicted_results'] = all_response_data
logger.error(f'log_session: {json.dumps(dict(request.session))}')
print('##############')
return redirect(f'predicted_results/')
predicted_results.py -- 这是重定向走的一个view,这里通过request.session.get('predicted_results')获取上面存储在session里的值,然后返回在前端页面。
from django.shortcuts import render
def predicted_results(request):
# print("json_data: ", json_data)
results = request.session.get('predicted_results')
import logging
logger = logging.getLogger('django')
logger.error(f'predicted_result_session: {results}')
return render(request, "result/predicted_results.html", {"predicted_results": results})
这里遇到了一个诡异的问题,通过python manages.py runserver 0.0.0.0:8000 访问该功能,提交文件处理后重定向的predicted_results正常。
但是,通过 uwsgi --ini uwsgi.ini 启动的应用,再访问该功能的时候,会出现有时可以有时不可以的随机事件。
排查发现前端返回的无结果即失败时,log日志为:
log_all_response_data: [{'result_shape': [{'Name': 'GCF_001546385.1_ASM154638v1', 'preds': 'coccus'}, {'Name': 'GCF_002243035.1_ASM224303v1',
'preds': 'coccus'}, {'Name': 'GCF_002243035.1_ASM224303v1-tst', 'preds': 'coccus'}]}, {'result_aerobic': [{'Name': 'GCF_001546385.1_ASM154638v
1', 'preds': 'anaerobe'}, {'Name': 'GCF_002243035.1_ASM224303v1', 'preds': 'anaerobe'}, {'Name': 'GCF_002243035.1_ASM224303v1-tst', 'preds': '
anaerobe'}]}, {'result_gram': [{'Name': 'GCF_001546385.1_ASM154638v1', 'preds': 'positive'}, {'Name': 'GCF_002243035.1_ASM224303v1', 'preds':
'positive'}, {'Name': 'GCF_002243035.1_ASM224303v1-tst', 'preds': 'positive'}]}]
log_session: {"predicted_results": [{"result_shape": [{"Name": "GCF_001546385.1_ASM154638v1", "preds": "coccus"}, {"Name": "GCF_002243035.1_AS
M224303v1", "preds": "coccus"}, {"Name": "GCF_002243035.1_ASM224303v1-tst", "preds": "coccus"}]}, {"result_aerobic": [{"Name": "GCF_001546385.
1_ASM154638v1", "preds": "anaerobe"}, {"Name": "GCF_002243035.1_ASM224303v1", "preds": "anaerobe"}, {"Name": "GCF_002243035.1_ASM224303v1-tst"
, "preds": "anaerobe"}]}, {"result_gram": [{"Name": "GCF_001546385.1_ASM154638v1", "preds": "positive"}, {"Name": "GCF_002243035.1_ASM224303v1
", "preds": "positive"}, {"Name": "GCF_002243035.1_ASM224303v1-tst", "preds": "positive"}]}]}
predicted_result_session: None
注意这里的predicted_result_session: None,参照predicted_results.py的代码是在这里打印的。而这predicted_results.py的作用是取得session,但是这里session为空,很诡异。
为了进一步确定是这里session为空,在浏览器进行查看upload_ml_matrix/和predicted_results/的Cookie情况
predicted_results/的请求Cookie中的sessionid正确与upload_ml_matrix/一致,但是响应Cookie的sessionid值为空,定位到这里就是问题的关键。
那什么情况会造成这样的随机事件?多进程执行时会导致这种情况,这恰与uwsgi的配置有关:
(我的uwsgi.ini配置)
[uwsgi]
socket = 127.0.0.1:8000
# http = 0.0.0.0:8000
chdir = /home/aq/bacapp
wsgi-file = bacapp/wsgi.py
master = true
processes = 2
threads = 4
vacuum = true
可以看到processes大于一个进程,这就属于多进程处理了,所以这是造成此bug的真凶。
如何解决?
LocalCache即本地的sessions是会话改变它也跟着变,所以我这里选择考虑使用像 Redis 或 Memcached 这样的共享缓存解决方案来替换 LocMemCache。这些服务可以在会话改变的情况下session不变。
我选择Redis,使用docker进行部署
docker pull redis
docker run -p 6666:6379 --name bac_redis -itd redis:latest
pip install django-redis -i https://mirrors.aliyun.com/pypi/simple/
# 服务器开启6666端口,然后进行settings.py配置django,下面是我的配置
CACHES = {
'default': {
# 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://111.231.32.238:6666/1',
'OPTIONS': {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
在 Django 配置中的 "LOCATION": 'redis://111.231.32.238:6666/1' 用于指定 Redis 服务器的连接信息。这个字符串是一个 URI 格式的地址,它的各部分含义如下:
redis://: 这是一个 URI 方案,指出使用的是 Redis。
111.231.32.238:6666: 这里指定了 Redis 服务器的地址和端口号。111.231.32.238 是本地主机的地址,6379 是 Redis 默认使用的端口号。如果您的 Redis 服务器配置在不同的地址或端口上,需要相应地修改这部分。
/1: 这部分指定了使用的 Redis 数据库。Redis 支持多个数据库(通常是从 0 到 15),您可以通过这个数字选择一个。在这个例子中,选择的是数据库 1。
优雅启动!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」