在使用 uwsgi 启动Python 脚本,或者项目的时候,会出现 访问不到 全局变量的问题。
大家都知道 uwsgi 是可以指定子进程的数目的,我设置了进程数 为1,那么 我有两个函数,那么他只会处理一个(在同一时刻)。uwsgi为了线程的并发,独立运行了多个进程,所以他具有多个全局变量。
-
uwsgi 的工作方式是启动指定个进程监听端口,接收到请求时就去执行对应的 uwsgi 入口文件,然后将结果返回给指定监听的端口。
-
当涉及到在一个 python 中修改全局变量或者多个线程访问一个变量的时候会不能获取到全局变量的修改。
因为每次请求都会重新执行一遍 python 脚本,从而每次都会重新初始化全局变量。
解决办法
将全局变量放置在进程里已经不可取了,所以将其拿出来,放入一个“公共访问区域”,让所有进程访问并修改该“公共访问区域”的全局变量。
- 目前该“公共访问区域”可以有多种实现方式:
-
使用现成的数据库:redis,mongodb,mysql等;
-
自己实现一个管理进程对数据进行管理(参考multiprocessing模块);
-
利用 uwsgi 内置的缓存功能
这里着重讲解第3种方式解决,可以最大限度的不依赖与第三方工具,并且借助 uwsgi
内置的方法.
关于“新一代”的缓存,它由uWSGI 1.9引入。 对于旧式缓存 (现在简单称其为“web缓存”),可以看看 WebCaching框架
uWSGI包含了一个非常快速、全内存访问、零IPC、SMP安全、不断优化、高度可调的、键值存储的简单的“缓存框架”。
单个uWSGI实例可以使用不同的设置,出于不同的目的,创建无限个不同的“缓存”。
- 通过如下命令启动
uwsgi
:
uwsgi --cache2 name=mycache,items=100 --socket :3031
这将会创建一个名为”mycache”
的缓存,它最多拥有100个项。每个项最大可以是64k。
- 或者在
uwsgi
配置文件中添加如下配置(第一行是注释说明)
; create a cache with 100 items (default size per-item is 64k)
cache2 = name=mycache,items=100,blocksize=5000000
配置创建了一个 名为 mycache
的缓存,它最多拥有 100 个项,每个项最大可以是:5MB, 其中 blocksize
用来设置单个缓存的大小,单位是字节(Byte)
在添加好 uwsgi
缓存后就可以在 python
脚本中设置 需要公共访问的变量了,通过引入 uwsgi
模块并且调用下面的方法便可以使用 uwsgi
缓存.
-
cache_get(key[,cache])
-
cache_set(key,value[,expires,cache])
-
cache_update(key,value[,expires,cache])
-
cache_exists(key[,cache])
-
cache_del(key[,cache])
-
cache_clear([cache])
如果调用该缓存 API
的语言/平台区分了字符串和字节 (例如 Python 3和Java
),那么你必须假设键是字符串,而值是字节 (或者在java之下,是字节数组)。否则,键和值都是无特定编码的字符串,因为在内部,缓存值和缓存键都是简单的二进制blob。
-
expires
参数 (默认为0,表示禁用) 是对象失效的秒数 (并当未设置purge_lru
的时候,由缓存清道夫移除,见下) -
cache
参数是所谓的“魔法标识符”,它的语法是cache[@node]
具体配置方式可以参考:
-
uWSGI 缓存烹饪指南:https://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/tutorials/CachingCookbook.html
-
uWSGI 缓存框架https://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/Caching.html
除此之外,推荐使用 uwsgi_cache
这个模块,这个模块利用了 python
本身的 pickle
模块对 uwsgi
中的cache api
进行了简单的封装,使得 uwsgi
可以进行缓存 python
的对象,在使用是需要注意的是避免缓存 pickle
不支持的对象,如 python
模块或者打开的文件等.具体原因不在此处讲解,可以参考 python pickle
模块 这篇博文.
uwsgi_cache
这个模块本身提供了两个方法,具体内容可以参考 uwsgi_cache
主页
- 使用
uwsgi_cache
模块完成缓存: 首先配置缓存:
uwsgi test.py --cache2 name=api,items=1000
然后在 test.py
文件中调用 uwsgi
缓存 api
进行全局缓存
from uwsgi_cache.cache import CacheManager
# :params:
# name: the name of the cache that you would like to create
# expires: the expire time of the cache data
# 这里需要传入两个参数 ,name 为缓存的名字,
# expires 为缓存的有效期, 0 表示禁用(即该缓存永不失效)
cache = CacheManager("cache_name_01", 0)
# 调用缓存方法
cache = 0
if not cache.exists("count"):
cache.set("count",0)
print("count value is %d",0)
else:
count = cache.get("count")
count +=1
print("count value is %d",count)
cache.set("count",count)
def application(environ, start_response):
status = '200 OK'
response_body = "count value is %d",count
response_header = [('Content-Type', 'text/html')]
start_response(status, response_header)
return [response_body.encode()]
启动uwsgi,便会发现 count 的值会随着每次请求调用而不断增加.
uwsgi test.py --cache2 name=api,items=1000