Django: общая / глобальная переменная, которая создается при запуске сервера и уничтожается при выходе из сервера - PullRequest
0 голосов
/ 06 мая 2019

Я бы хотел использовать Django в качестве реле на другой слой. Когда пользователь делает запрос, клиент thrift вызывает функцию, которая обращается к другому программному обеспечению для получения результата.

Я понимаю потенциальные проблемы безопасности потоков, поэтому будет существовать пул объектов, основанный на многопроцессорности Python, и каждый пользовательский запрос будет выдавать один, использовать его и возвращать обратно.

Пул объектов должен быть инициализирован в начале программы и уничтожен (надеюсь, чисто) при выходе из программы (когда сервер прерывается с помощью SIGINT). Мотивация к этому вопросу состоит в том, чтобы знать, как сделать это правильно без взломов.

Единственный способ, который я нашел до сих пор, - это следующий прототип с глобальными переменными, учитывая, что ниже представлен файл представлений с представлениями на основе функций:

clients_pool = ClientsPool("127.0.0.1", 9090, size=64) # pool size

def get_data(request):
    global clients_pool
    c = clients_pool.pop()  # borrow a client from the pool
    res = c.get_data(request.body)  # call the remote function with thrift
    clients_pool.release(c)  # restore client to the pool
    return HttpResponse(res)


def get_something(request):
    global clients_pool
    c = clients_pool.pop()  # borrow a client from the pool
    res = c.get_something(request.body)  # call the remote function with thrift
    clients_pool.release(c)  # restore client to the pool
    return HttpResponse(res)

Это правильный способ сделать это? Или Django предлагает лучший механизм для этого?

1 Ответ

1 голос
/ 06 мая 2019

Я бы позаботился о том, чтобы здесь были достигнуты несколько целей.Сначала убедитесь, что всегда создается только один экземпляр вашего менеджера пула.Вы можете поместить его в __init__.py вашего приложения.Я не знаю, безопасен ли этот поток.Я сомневаюсь в этом.

Во-вторых, вы хотите делегировать управление пулом прикладному уровню.Прямо сейчас вы управляете пулом в слое представления.Вы всегда хотите удостовериться, что клиенты пула выпущены, я полагаю.Это привело бы к чему-то вроде этого:

# [app_name]/__init__.py

class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


class PoolManager(metaclass=Singleton):
    def __init__(self, *args, **kwargs)
        self.pool = ClientsPool(*args, **kwargs)


pool_manager = PoolManager(host='127.0.0.1', port=9090, size=64)

# views.py / consider moving the context manager to seperate file
from [app_name] import pool_manager


class PoolContextManager:
    def __init__(self):
        self.pool = pool_manager

    def __enter__(self):
        return self.pool.pop()

    def __exit__(self, type, value, traceback):
        self.pool.release(c)


def get_data(request):
    with PoolContextManager() as pm:
        res = pm.get_data(request.body)  
        return HttpResponse(res)


def get_something(request):
    with PoolContextManager() as pm:
        res = pm.get_something(request.body) 
        return HttpResponse(res)
...