在Django中使用线程池的一次尝试

3,087 阅读1分钟

注意

由于作者也是培训班选手,所以本文只涉及实现部分,不对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)

参考

本文参考了这位大神的文章

参考连接