PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Django ORM rò rỉ kết nối khi sử dụng ThreadPoolExecutor

Tôi đoán rằng ThreadPoolExecutor không phải là những gì đang tạo ra kết nối DB, nhưng các công việc phân luồng là những công việc giữ kết nối. Tôi đã phải giải quyết vấn đề này rồi.

Tôi đã kết thúc việc xây dựng trình bao bọc này, để đảm bảo rằng các luồng được đóng theo cách thủ công bất cứ khi nào công việc được thực hiện trong ThreadPoolExecutor. Điều này sẽ hữu ích trong việc đảm bảo các kết nối không bị rò rỉ, cho đến nay tôi chưa thấy bất kỳ sự rò rỉ nào khi sử dụng mã này.

from functools import wraps
from concurrent.futures import ThreadPoolExecutor
from django.db import connection

class DjangoConnectionThreadPoolExecutor(ThreadPoolExecutor):
    """
    When a function is passed into the ThreadPoolExecutor via either submit() or map(), 
    this will wrap the function, and make sure that close_django_db_connection() is called 
    inside the thread when it's finished so Django doesn't leak DB connections.

    Since map() calls submit(), only submit() needs to be overwritten.
    """
    def close_django_db_connection(self):
        connection.close()

    def generate_thread_closing_wrapper(self, fn):
        @wraps(fn)
        def new_func(*args, **kwargs):
            try:
                return fn(*args, **kwargs)
            finally:
                self.close_django_db_connection()
        return new_func

    def submit(*args, **kwargs):
        """
        I took the args filtering/unpacking logic from 
   
        https://github.com/python/cpython/blob/3.7/Lib/concurrent/futures/thread.py 
        
        so I can properly get the function object the same way it was done there.
        """
        if len(args) >= 2:
            self, fn, *args = args
            fn = self.generate_thread_closing_wrapper(fn=fn)
        elif not args:
            raise TypeError("descriptor 'submit' of 'ThreadPoolExecutor' object "
                        "needs an argument")
        elif 'fn' in kwargs:
            fn = self.generate_thread_closing_wrapper(fn=kwargs.pop('fn'))
            self, *args = args
    
        return super(self.__class__, self).submit(fn, *args, **kwargs)

Sau đó, bạn chỉ có thể sử dụng cái này:

    with DjangoConnectionThreadPoolExecutor(max_workers=15) as executor:
        results = list(executor.map(func, args_list))

... và tin tưởng rằng các kết nối sẽ đóng.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cài đặt và kết nối với PostgreSQL 10 trên Ubuntu 16.04

  2. Entity Framework ObjectContext -> các cuộc gọi SQL thô đến DBMS bản địa

  3. Postgresql 9.x:Chỉ mục để tối ưu hóa các truy vấn `xpath_exists` (XMLEXISTS)

  4. Chuyển đổi kết quả của truy vấn PostgreSQL sang XML, sử dụng PHP DOM

  5. Chọn các cột có tên cột cụ thể trong PostgreSQL