Django设置全局对象,仅在启动时初始化一次.

2018.10.23

github上的lazybird/django-solo项目可以实现Django中的单例模式.
通过:

  1. 维护该模型的表中只有一行,保证对象全局一致;
  2. 配合实现cache机制,让对象常驻内存.

结合这两点实现我们要的全局对象的效果, 并且在django-models之内,便于管理.

2018.10.10

部署到uwsgi时默认配置也不会有问题, 多进程各请求可以访问共享数据.
只需考虑并发锁.
与uwsgi的工程加载模式有关.
lazy选项默认为false.
uwsgi将django项目读取一次之后,在master进程完成初始化, 包括我们设置的全局变量的代码块. 之后获取request直接在master中进行fork().这也是所谓preforking模式, 可以保证运行过程当中不需要再从磁盘读取代码文件.
lazy设置为true就会导致共享变量在各个进程当中存在多个独立副本的问题. 经过测试, 当请求频率变高, uwsgi将请求分配到其他进程时, 访问的共享变量就开始不一致.

2018.09.28

单进程的本地测试时没有问题,部署到uwsgi时,当uwsgi使用master-worker的方式启动多个Django Application,各进程之间互相隔离,将全局变量写在view当中会导致各进程间不一致。

解决方法:

依赖进程外的持久化方案,即数据库或内存数据库。
最佳的实践是使用Redis作为Django的cache,再利用django对cache的接口实现便利的redis操作。
但同时要注意,多进程并发操作redis会带来一致性问题。

解决方法:

  1. 尽可能使用Redis自带原子操作,如incr,decr等实现值的自增;
  2. 各个进程在操作之前使用SETNX加锁。

原文

解决问题:

HTTP是无状态的,但是我们希望记录一些前后多次requests中有关联的数据, 又或许在计算密集的模块有些只读模型数据只需要保存一份,供多次请求读取,而不需要每次请求都重新读取一遍.

实现方法:

将共享python变量写在views函数之外,view函数内通过global访问.

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.
num = 0
print("loading once")

def check(request):
	global num
	num += 1
	return HttpResponse("complete with " + str(num))

效果

Django设置全局对象,仅在启动时初始化一次._第1张图片

从输出可以看到"loading once",num变量仅加载了一次,之后处理多次请求.

响应输出:

6
7
8

生产环境

使用python pickle完成object的序列化, 再用memcached和redis保存大文件数据更可靠, 每次请求从memcached或redis当中获取.

实际用途

目标:

服务器加载pyltp自然语言处理框架, 暴露REST API给客户端, 客户端发送要查询的文本,响应给出处理结果.

问题:

ltp处理依赖模型, 如分词器需要加载对应分词模型数据, 数据只读, 只需一次加载,不需要多次为每次请求重复加载.

全局变量实践:

在view函数以外,服务器启动时完成分词器的初始化,每个视图当中使用global获取全局对象.

你可能感兴趣的:(python学习笔记,django,python3,python,django,全局变量,问题解决)