Перезапись переменной класса и одновременных Flask запросов - PullRequest
1 голос
/ 09 апреля 2020

Я использую сервер python Flask для выполнения сложных алгоритмов, один из которых назначает кабели для труб.

class Tube:
    max_capacity = 5
    cables: List[str]

    def has_capacity(self):
        return len(self.cables) < self.max_capacity

Максимальная емкость всегда была 5, но теперь появился новый клиент на самом деле у него есть трубки, которые могут вмещать 6 кабелей.
Когда я получаю запрос, я просто устанавливаю Tube.max_capacity = request.args.get('max_capacity', 5). Тогда каждый экземпляр Tube будет иметь правильную настройку.

Мне было интересно, будет ли это работать, если одновременно обрабатывается несколько запросов?
Является ли Flask (я использую Gunicorn как WSGI) все процессы отделены друг от друга, так что это безопасно делать? Я не хочу заканчиваться странными ошибками, потому что максимальная емкость изменилась на полпути через запрос, потому что поступил другой запрос.

РЕДАКТИРОВАТЬ: Я попробовал это, и, кажется, работает как задумано:

@app.route('/concurrency')
def concurrency():
    my_value = randint(0, 100)
    Concurrency.value = my_value
    time.sleep(8)
    return f"My value: {my_value} should be equal to Concurrency.value {Concurrency.value}"


class Concurrency:
    value = 10

Тем не менее, я хочу знать больше о том, как несколько запросов Flask / Gunicorn работают, чтобы быть уверенными.

1 Ответ

1 голос
/ 09 апреля 2020

Приложения WSGI обычно обслуживаются с использованием нескольких процессов - в конечном итоге на разных серверах - и запросы от одного и того же пользователя будут обрабатываться первым доступным процессом. IOW: вы NOT хотите изменить любые переменные уровня модуля или класса для каждого запроса, это ** гарантировано *, чтобы все испортить.

Невозможно точно сказать вам, как решить проблему без особого контекста, но во всех случаях вам придется переосмыслить свой дизайн.

РЕДАКТИРОВАТЬ :

как ведут себя процессы? Если один из них устанавливает значение, другой процесс также видит это значение?

Конечно, нет - каждый процесс полностью изолирован от других - поэтому изменение модуля- переменная уровня или атрибут класса будут влиять только на текущий процесс. Но поскольку процессы не привязаны к клиентам (процесс, который будет обрабатывать данный запрос, абсолютно непредсказуем), такого рода изменения в одном процессе не обязательно будут видны в следующем запросе, если он обслуживается другим процессом. И:

Или, процесс используется повторно, а затем все еще имеет значение из предыдущего запроса?

процесс, конечно, используется повторно, но это не означает тот же процесс будет повторно использован для следующего запроса от того же пользователя - и это вторая часть проблемы: при обслуживании другого пользователя ваш процесс все равно будет использовать «обновленное» значение max_capacity из предыдущий пользователь.

Итак, вы делаете гарантированно чтобы все испортить для всех ваших пользователей. Вот почему мы используем внешние (вне процесса) средства для хранения и обмена данными для каждого пользователя между запросами - либо сеансами (для нестабильных данных), либо базой данных (для постоянного хранения).

...