python flask请求对象线程隔离

flask框架多线程隔离

1. 调试环境: 客户端发送10个请求,flask : app.run 单进程单线程 请求一个一个执行,不能大量处理请求
可以开启threaded参数以保证多线程

app.run(debug=app.config['DEBUG'], threaded=True)

2. 部署开发环境: webserver开启多线程 nginx apache tomcat
3. flask的werkzeug的Local对象管理多线程
字典 request = {k:v}
多线程下 每个线程都有唯一标识作为key,请求对象对位value
线程的id号作为键,实现线程隔离
字典 保存数据
操作数据,werkzeug库 local模块 Local对象 实现线程隔离(字典)
定义一个L对象,线程隔离对象
t1 L.a t2 L.a 互不影响
Local对象 线程id号作为键

4. 变量修改

class A:
    b = 1

my_obj = A()

def worker():
    # 新线程修改b的值
    my_obj.b = 2

t = threading.Thread(target=worker, name='wang')
t.start()
time.sleep(1)
print(my_obj.b)   # 2
# 实例化三个对象 以隔离
request1 = Request()
request2 = Request()
request3 = Request()

python flask请求对象线程隔离_第1张图片

5. 线程的隔离对现象Local:新线程的修改不影响主线程的值

from werkzeug.local import Local
class A:
    b = 1

my_obj = Local()
my_obj.b = 1

def worker():
    # 新线程修改b的值
    my_obj.b = 2  # 新线程的需改不影响主线程,线程的隔离
    print('in new thread b is : ' + str(my_obj.b))  # 2

t = threading.Thread(target=worker, name='wang')
t.start()
time.sleep(1)
# 主线程
print('in main thread b is : ' + str(my_obj.b))   # 1

6. 线程隔离的栈 LocalStack
python flask请求对象线程隔离_第2张图片

两种栈:_request_ctx_stack _app_ctx_stack
管理上下文,线程隔离的栈 LocalStack()

_request_ctx_stack = LocalStack()
_app_ctx_stack = LocalStack()

LocalStack Local 字典 关系:
Local用字典的方式实现隔离
LocalStack封装了Local对象,作为一个属性,形成一个线程隔离的栈结构
如果一次封装解决不了问题,那么就再来一次~

7. LocalStack的push pop top

from werkzeug.local import LocalStack

# 栈Stcak的特性

s = LocalSrack()
s.push(1)
print(s.top())  # 1
print(s.top)    # 1
print(s.pop())  # 1
print(s.top)    # None

# 栈 后进先出
s.push(1)
s.push(2)
print(s.top)  # 2
print(s.top)  # 2
print(s.pop())  # 2
print(s.top)  # 1

线程隔离(对象:requet请求上下文,app应用上下文)

from werkzeug.local import LocalStack
import time
import threading

# Local的特性
# 两个栈互不影响,线程隔离

my_stack = LocalStack()
my_stack.push(1)
print('栈顶元素为:', my_stack.top)  # 1

def worker():
	# 新线程
	print('is a new thread', my_stack.top)  # None
	my_stack.push(2)
	print('is after value: ', my_stack.top) # 2
	
new_t = threading.Thread(target=worker, name='wang')
new_t.start()
time.sleep(1)

# 主线程
print('主线程栈顶数据为:', my_stack.top)  # 1

8. 使用线程隔离的意义在于:
使当前线程能够正确引用到他自己所创建的对象,而不是引用到其它线程创建的对象
对象是保存状态的地方
9. flask中线程隔离的有:
request session g

10. flask梳理

  1. 线程隔离对象 LocalStack()和Local(),被线程隔离对象由线程隔离对象创建
  2. 引用上下文和flask的app对像有区别,flask核心对象app全局只有一个(app在主线程中,request每个线程都有一个)
  3. App_Context把flask的核心对象app对象作为属性保存起来,RequestContext把request对象封装保存
  4. current_app不是线程隔离的app,全局只有一个app对象,不同的id号对应的都是app对象;
  5. request多线程有多个请求request对象,是线程隔离的
  6. current_app指向LocalStack.top栈顶元素(AppContext)的app属性(top.app(AppContext.top),flask的核心对象)
  7. request指向LocalStack.top(RequestContext)的栈顶元素,top.request = Request
  8. 全局计数器可以不再flask做(线程安全),mysql或者redis中做计数器

你可能感兴趣的:(flask,python,flask的Local线程隔离)