Python uwsgi 获取不到全局变量

原创
2018/11/04 22:17
阅读数 5.7K

使用uwsgi启动的时候,涉及到多request线程访问同一个全局变量,发现不能获取到全局变量的值的修改。严重怀疑是uwsgi的线程机制的问题,因为uwsgi是可以指定子进程的数目的,然而我设置子进程数目为1,之后,在处理函数1的时候是不能同时处理函数2的,怎么说,有点类似于javaweb中,uwsgi为了线程的并发,独立运行了多个进程,所以具有多个全局变量?


在猜想 uwsgi 的工作方式是启动指定个进程监听端口,当接收到请求时执行对应的 uwsgi 入口文件,然后将结果返回给指定监听的端口.当涉及到在一个 python 中修改全局变量或者多个线程访问一个变量的时候会不能获取到全局变量的修改.因为每次请求都会重新执行一遍 python 脚本,从而每次都会重新初始化全局变量.

解决办法

思路是这样子的:将全局变量放置在进程里已经不可取了,所以将其拿出来,放入一个“公共访问区域”,让所有进程访问并修改该“公共访问区域”的全局变量。

目前该“公共访问区域”可以有多种实现方式:

  1. 使用现成的数据库:redis,mongodb,mysql等;
  2. 自己实现一个管理进程对数据进行管理(参考multiprocessing模块);
  3. 利用 uwsgi 内置的缓存功能

这里着重讲解第3种方式解决,可以最大限度的不依赖与第三方工具,并且借助 uwsgi 内置的方法.

参考链接

uWSGI缓存烹饪指南

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_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
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部