注意
由于作者也是培训班选手,所以本文只涉及实现部分,不对Python线程和Django的实现进行讨论,另外本次修改只是一次尝试,并未实际应用于生产环境。本文可能存在错误和误区,欢迎批评指点。
场景
项目中每次接收到Http Request时,需要进行数据库插入处理。如果进行同步保存,则可能使Response变慢,于是使用线程(Thread)进行异步保存。在得知每次都创建线程会使系统开销变大,于是决定尝试使用线程池(ThreadPoolExecutor)。
运行环境
- Django 3.0.6
- Python 3.8
修改为线程池之前的代码
# 伪代码
from threading import Thread
def save_by_thread(self):
log = Log()
log.content = "xxx"
log.save()
def save(self):
thread = Thread(target=self.save_by_thread)
thread.start()
自制线程池代码
# thread_pool.py
class ThreadPool(object):
def __init__(self):
self.executor = ThreadPoolExecutor(min(32, os.cpu_count() + 4))
self.dbs = ["default"]
def submit_task(self, fn, *args, **kwargs):
"""
异步执行任务
:param fn:
:param args:
:param kwargs:
:return:
"""
future = self.executor.submit(fn, *args, **kwargs)
return future
def submit_db_task(self, fn, *args, **kwargs):
"""
异步执行数据库任务
:param fn:
:param args:
:param kwargs:
:return:
"""
self.close_old_connections()
future = self.submit_task(fn, *args, **kwargs)
return future
def close_old_connections(self):
"""
查看数据库连接是否有效,无效则关闭
:return:
"""
connections = local()
for db in self.dbs:
if hasattr(connections, db):
conn = getattr(connections, db)
conn.close_if_unusable_or_obsolete()
global_thread_pool = ThreadPool()
使用
# test.py
form thread_pool import global_thread_pool
# 执行普通任务
global_thread_pool.submit_task(your_function)
# 执行数据库任务
global_thread_pool.submit_db_task(your_function)
参考
本文参考了这位大神的文章