Flask的app,去用gunicorn启动,很自然的参考别处的写法,设置了4个worker:
同时,为了实现websocket,添加了
-k flask_sockets.worker
然后用supervisor去管理,配置如下:
/Users/crifan/dev/dev_root/daryun/Projects/RunningFast/sourcecode/RunningFast-Server/supervisor.conf
command=/root/Envs/RunningFast/bin/gunicorn -w 4 -b 0.0.0.0:21085 -k flask_sockets.worker run:app & |
此处,Flask内部使用了:
全局变量,用于保存当前有效的websocket的连接
gWsDict = {} |
但是现象出了问题:
对于之前保存了的变量值:
added new ws for user user-cc680b0a-8d04-4f2b-8ad9-c6fefb527861 , gWsDict={u’user-cc680b0a-8d04-4f2b-8ad9-c6fefb527861′: <geventwebsocket.websocket.WebSocket object at 0x7f3a36749e50>} |
但是后来别的请求中,却获取不到:
DEBUG in Websocket [/root/RunningFast/staging/runningfast/resources/Websocket.py:138]: gWsDict={} |
-》
之前也遇到了,类似现象,但是已经解决了:
其中也提到了:
由于多线程,会导致不同线程内部,其实有自己的独立的全局变量区域
-》Flask多个线程中,各自有自己不同的全局变量
-》别的线程中,全局变量赋值了,但是另外的线程中的该全局变量还是没有值
-》可能要涉及到进程,线程,数据同步的问题
去看看:
Understanding Contexts in Flask
python – Preserving global state in a flask application – Stack Overflow
python – Flask global variables – Stack Overflow
-》
flask.g是基于每个request来说的,全局
Flask的app,可能运行在多个进程(中的多个线程)
-》说解决办法就是:
不要用这种全局变量
改用数据库(或者其他方式,比如缓存)去存储
flask how store global value
python – How to share the global app object in flask? – Stack Overflow
[ASK Flask] Application wide variable:flask
和我的需求一样,
提到了用:
memcached
redis
-》此处借用我的,之前已经正在使用的redis?
flask redis store global value
python – Inconsistent globals in Flask – Stack Overflow
->也是推荐用redis
Flask-Cache — Flask-Cache 0.13 documentation
-》
好像是可以通过:
Flask-Cache去保存全局的变量(对象)的
flask-cache store global value
flask-cache 保存 全局变量
Using Flask Cache | python | flask | BrunoRocha.org | Python web development
-》
Caching arbitrary objects
from cache import cache def function(): cached = cache.get(‘a_key’) if cached: return cached result = do_some_stuff() cache.set(‘a_key’, result, timeout=300) return result |
Memoized? · Issue #16 · thadeusb/flask-cache
-》
直接使用Flask中的Werkzeug自带的cache
好像就不用额外安装Flask-Cache了?
然后发现可以考虑:
之前就想到的方案
把此处的dict对象变量,用pickle序列化为字符串后,存到redis中,
读取时再反序列化为对象
就可以了?
搜:
python redis store object
参考:
python – how to store a complex object in redis (using redis-py) – Stack Overflow
import pickle import redis r = redis.StrictRedis(host=’localhost’, port=6379, db=0) obj = ExampleObject() pickled_object = pickle.dumps(obj) r.set(‘some_key’, pickled_object) unpacked_object = pickle.loads(r.get(‘some_key’)) obj == unpacked_object |
不过有说:
反序列化时可以执行任意代码-》不够安全
-》JSON方案更安全
import json import redis r = redis.StrictRedis(host=’localhost’, port=6379, db=0) images= [ {‘type’:’big’, ‘url’:’….’}, {‘type’:’big’, ‘url’:’….’}, {‘type’:’big’, ‘url’:’….’}, ] json_images = json.dumps(images) r.set(‘images’, json_images) unpacked_images = json.loads(r.get(‘images’)) # python3: # unpacked_images = json.loads(r.get(‘images’).decode(‘utf-8’)) images == unpacked_images |
python – get object from redis without eval? – Stack Overflow
def set_value(redis, key, value): redis.set(key, pickle.dumps(value)) def get_value(redis, key): pickled_value = redis.get(key) if pickled_value is None: return None return pickle.loads(pickled_value) |
搜:
json.dumps 对象
“变量的内容又回来了!
当然,这个变量和原来的变量是完全不相干的对象,它们只是内容相同而已。”
-》这样还是无法实时保存对应的变量啊。。。
-》因为我内部要去获取对应dict中的websocket对象,然后去用websocket去发送消息的。。。
6.2 读写JSON数据 — python3-cookbook 2.0.0 文档
Python实现支持JSON存储和解析的对象 – Adan – 博客频道 – CSDN.NET
【总结】
最后实在不行了。
暂时先把gunicorn的worker设置为1:
/Users/crifan/dev/dev_root/daryun/Projects/RunningFast/sourcecode/RunningFast-Server/supervisor.conf
[program:runningfast_stable] directory=/root/RunningFast/stable command=/root/Envs/RunningFast/bin/gunicorn -w 1 -b 0.0.0.0:21084 -k flask_sockets.worker run:app & … [program:runningfast_staging] directory=/root/RunningFast/staging command=/root/Envs/RunningFast/bin/gunicorn -w 1 -b 0.0.0.0:21085 -k flask_sockets.worker run:app & … |
然后继续使用全局变量的方案,暂时就可以先保证可以通过全局变量获得对应的webscoket的示例对象了。
-》等以后找到更好的办法,再说。
【后记】
后来,是避开了 全局变量的方法,而用:
去解决了,此处的,实时的对象,的传递和处理的问题。
转载请注明:在路上 » 【规避解决】Flask中开了多个worker时如何使用全局变量