LINUX.ORG.RU

Как программно перезапустить веб-приложение Nginx+Bottle

 , ,


0

1

Приложение меняет параметр и перезаписывает ini-файл.
Но на сайте это изменение не отражается, пока вручную не перезапустишь nginx.

Вопрос: как программно перезапустить веб-python-bottle-приложение, запущенное через nginx, причем чтоб метод работал и линуксе и в винде?

★★★★★

Можно просто в веб-python-bottle-приложении реализовать SIGHUP-хедлер, который будет перечитывать конфиг, а из приложения, которое меняет параметр, посылать SIGHUP после его смены твоему веб-приложению.

Насчёт оффтопика не подскажу.

theNamelessOne ★★★★★
()

А кто конкретно перезаписывает конфиг? Само веб-приложение перезаписывает свой конфиг, или какое-то другое?

Как у тебя приложение запускается и как работает с Nginx?

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

А кто конкретно перезаписывает конфиг?

Само же приложение и перезаписывает.
Как я понял проблема в том, что Nginx запускает несколько копий приложения. И когда одно из них перезаписывает параметр, в других копиях параметр остаётся.

Тут нужно или параметр перечитывать в других приложениях (как выше советуют), либо заставлять эти приложения перезапуститься.

Как у тебя приложение запускается и как работает с Nginx?

NGinx запускается заранее автостартом и слушает TCP-порт 8080 (со стороны клиентов 80й порт есесьно).

Приложение запускается питонячим же скриптом:

#!/usr/bin/env python2

import os

from bottleapp import app

if __name__ == '__main__':
  app.run(server='flup', host='127.0.0.1', port=8080, debug=True, reloader=True)

Nginx на 80-м порту принимает запросы веб-клиентов и переадресовывает их на несколько копий приложений (у меня на компе стоит worker_processes 2;).

Novator ★★★★★
() автор топика
Ответ на: комментарий от theNamelessOne

посылать SIGHUP после его смены твоему веб-приложению

А как обнаружить другие процессы, чтобы им послать SIGHUP? И да, мне-таки надо чтоб в винде тоже работало.

Novator ★★★★★
() автор топика
Ответ на: комментарий от theNamelessOne

Либо просто сделай внутренний эндпоинт у веб-приложения, который будет дёргать твоё приложение

А как это сделать? Нужен фрагмент кода или ссылка на него.

Novator ★★★★★
() автор топика
Ответ на: комментарий от theNamelessOne

В описании сигналов написано:

Некоторое внимание должно быть уделено если сигналы и потоки используется вместе в одной программе. Основное что нужно запомнить при одновременном использовании сигналов и потоков: всегда выполнять операции signal() в основном потоке выполнения. Любой поток может выполнять alarm(), getsignal(), pause(), settimer(), gettimer(); только главный поток может устанавливать новые обработчики сигналов и он же единственный кто может получать сигналы (это обеспечивается модулем signal, даже если базовая реализация потоков поддерживает посылку сигналов индивидуальным потокам). Это означает что сигналы не могут быть использованы для межпотокового сообщения. Используйте блокировки вместо этого.

А в bottle FastCGI как раз вроде сделан через threads.

Самое надёжное, это как-то обнаружить все другие процессы и грохнуть их, после чего nginx их перезапустит. План такой, но как сделать - не знаю.

Novator ★★★★★
() автор топика
Последнее исправление: Novator (всего исправлений: 1)

Тогда такой вопрос: есть в bottle какой-то механизм, типа таймера, который время от времени глядит например в какую-то папку или смотрит размер/время правки файла?

Novator ★★★★★
() автор топика
Ответ на: комментарий от Novator

А что запускает этот питонячий скрипт? Через это и перезапускай. Или перечитывай конфиг на каждый реквест, почему бы и нет?

PolarFox ★★★★★
()
Ответ на: комментарий от Novator

Боттл — это даже не микрофреймворк, это один единственный модуль (по крайней мере был, когда я последний раз смотрел в код) на пару сотен строк, там вообще ничего нет.

Отслеживать изменения в файле можешь, конечно, безотносительно боттл. Но правильней было бы зарулить всё с помощью Redis.

WitcherGeralt ★★
()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

Десятки запросов к БД чтобы отрендерить главную страницу в вебдеве в порядке вещей, а рядом сидящий файл прочитать, который наверняка в кеше ютится, почему-то сразу тупо и медленно.

PolarFox ★★★★★
()
Ответ на: комментарий от PolarFox

Десятки запросов к БД чтобы отрендерить главную страницу в вебдеве в порядке вещей

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

WitcherGeralt ★★
()
Ответ на: комментарий от Novator

А как обнаружить другие процессы, чтобы им послать SIGHUP

Нужно, чтобы приложение при запуске записывало PID в файл по какому-то известному пути (например, где-нибудь в /var/run). Другое приложение может найти этот PID-файл и прочитать оттуда PID.

theNamelessOne ★★★★★
()
Ответ на: комментарий от Novator

А как это сделать? Нужен фрагмент кода или ссылка на него.

Это уже смотри доки для своей либы.

theNamelessOne ★★★★★
()
Ответ на: комментарий от Novator

А в bottle FastCGI как раз вроде сделан через threads.

Ну и что? В твоей цитате написано, что нужно сделать.

theNamelessOne ★★★★★
()
Ответ на: комментарий от PolarFox

Или перечитывай конфиг на каждый реквест, почему бы и нет?

INI и перечитывается при каждом запуске скрипта.
Но по каким-то причинам (полагаю, из-за того, что nginx/fcgi заранее запускает несколько процессов/потоков) просто при смене ini-файла, запросы выполняются со старым параметром.

Хотя... возможно придётся перечитывать ini именно на каждый запрос, а не в начале запуска скрипта, как сделано сейчас... Короче, геммор на ровном месте, ненавижу современную вебню.

Novator ★★★★★
() автор топика
Ответ на: комментарий от WitcherGeralt

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

deep-purple ★★★★★
()
Ответ на: комментарий от WitcherGeralt

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

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

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

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

Пойди дальше, предложи взять апач и запускать приложуху как cgi. Почему нет?

WitcherGeralt ★★
()
Ответ на: комментарий от Novator

А как обнаружить другие процессы, чтобы им послать SIGHUP?

killall

rach_linux
()
Ответ на: комментарий от Novator

При запуске процессов записать их пиды в файлик? А при обнаружении изменения ini файлика поочерёдно их грохнуть. ДЛя этого можно написать килера который как демон будет висеть и всё что делать так отслеживать состояние ini файла и убивать всё из файлика с пидами при изменении ini файла, ну или посылать сигнал самим процессам тем или иным способом что-бы они самоубивались. Возможно что у nginx есть хуки для этого тогда наверное можно на lua написать хук который всё это убудет делать.

Хотя в идеале процессы должны просто по сигналу перечитывать ini файл и перенстраиваться, сингал им слать по localhost:88005553535 пусть раз в секунду чекают.

А вообще я бы над архитектурой призадумался и вот эту фичу с перезапуском при перезаписывании как-то свёл к чему то иному если возможно.

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 3)
Ответ на: комментарий от LINUX-ORG-RU

Nginx не управляет приложениями. Но есть Unit, uwsgi, gunicorn и много чего ещё.

Я так и не понял как ТС запускает приложухи и зачем ему рестартовать nginx.

WitcherGeralt ★★
()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

Я вот хз. Но давай придумаем безумное

Есть стартовые скрипты .sh/.bat которые сначала на localhost:100500 запускают пулл процессов затем запускается проксирующий nginx в конфиге которого прописаны эти порты для проброса в мир, один из процессов пула перезаписывает стартовый in конфиг файл в котором указано что теперь все процессы должны вещать на иной порт, также перезаписвыавется nginx.conf для новых портов и теперь что-бы всё это завелось, надо перезапустить и все процессы и nginx через грох стартового скрипта.

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

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)

Заверни приложуху в systemd демон и рестартуй его, через os.execv

rikimaru
()
Ответ на: комментарий от Novator

геммор на ровном месте, ненавижу современную вебню

Ну, многопоточность же. Запускай в 1 воркер, и не будет тебе никаких проблем :)

@PolarFox

Или перечитывай конфиг на каждый реквест, почему бы и нет?

Не будет ли тут (редкой) проблемы из-за многопоточности? (ну типа один пишет «аб», и не успел записать «б», а второй прочитал «а»). Или тут спасает кэш диска?

@WitcherGeralt

правильней было бы зарулить всё с помощью Redis

А если я использую Постгре как основную, лучше всё-равно с Редисом, или можно всё в ПГ?

the1 ★★
()
Ответ на: комментарий от the1

В реляционных бд хранят большие объёмы нормализованных данных, а редис используют в основном для того, чтобы что-то пошаришь между сервисами, для кеша и pub-sub. Я предлагаю именно шарить нужные значения из конфига, которые изменяются, а не хранить конфиг в бд.

Есть ещё специализированные хранилища конфигурации типа etcd, но это совсем уж оверкилл.

WitcherGeralt ★★
()
Ответ на: комментарий от the1

Не будет ли тут (редкой) проблемы из-за многопоточности? (ну типа один пишет «аб», и не успел записать «б», а второй прочитал «а»). Или тут спасает кэш диска?

Надо писать обновлённый конфиг в темпфайл, а потом перемещать на место текущего конфига. В пределах одной локальной ФС перемещение атомарно.

PolarFox ★★★★★
()
Ответ на: комментарий от WitcherGeralt

В реляционных бд хранят … а редис используют в основном …

Спасибо. Я примерно понимаю… Я в смысле скорости имел ввиду. Прямой SQL-запрос в Постгре vs. Редис. (как я понял, ORM сильно тормозит по сравнению с raw db access).

А можно кстати улучшить метод перечитывания конфига каждый риквест – сделать конфиг в .py? При обновлении («в темпфайл, а потом перемещать») он откомпилится 1 раз, а читаться будет уже быстро, каждый запрос. Как такой вариант? @PolarFox

PS. «Прямой SQL-запрос» – на чтение в смысле, запись будет редкой.

the1 ★★
()
Последнее исправление: the1 (всего исправлений: 2)
Ответ на: комментарий от the1

Не, не нужно так делать, лучше просто текстовый файл читать.

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

А от состояния гонки перемещение файла тебя не спасёт, при двух одновременных запросах на изменение разных полей всё равно будет ненулевая вероятность потерять одно из них.

WitcherGeralt ★★
()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от the1

А можно кстати улучшить метод перечитывания конфига каждый риквест – сделать конфиг в .py? При обновлении («в темпфайл, а потом перемещать») он откомпилится 1 раз, а читаться будет уже быстро, каждый запрос. Как такой вариант?

Писать программой в исполняемый файл и потом его же исполнять? Не, лучше не надо, потенциальная дыра. Да и будет соблазн проявлять фантазию в этом .py файле. Ещё питон кеширует импорты, его придётся уговаривать переисполнять модуль.

Парсинг json/toml/xml или чего там у тебя всяко быстрее выполнится чем питоновский код.

И вообще, лучше храни значения в какой-нибудь БД. Хотя бы sqlite, он в питоне есть всегда и дополнительного сисадминства по сравнению с обычным файлом не требует.

PolarFox ★★★★★
()
Последнее исправление: PolarFox (всего исправлений: 1)
Ответ на: комментарий от PolarFox

Обычный importlib.realod, это в __builtins__ ещё недавно было.

питон кеширует импорты

Это не кеш, модуль — полноценный объект с состоянием. Если это не простая оговорка, то имей ввиду.

WitcherGeralt ★★
()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

importlib.reload модуль перегрузит, да. Только если кто-то где-то сделал from reloaded_module import something, то он этот релоад не заметит, придётся за этим следить. Снаружи jupiter и прочих вариантов repl и всяких мудрёных систем плагинов можно считать за code smell.

PolarFox ★★★★★
()
Ответ на: комментарий от PolarFox

Это в сущности то же самое, что взять атрибут объекта в переменную, сам объект снести и заменить. Ясен пень, головой нужно думать.

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Просто от модуля, по сравнению с другими объектами, обычно не ожидают что там на лету что-то поменяется.

PolarFox ★★★★★
()
Ответ на: комментарий от PolarFox

У меня, кстати, так девочка джун что-то в тестах мокала, я ржал, а она полдня не могла понять, что не так.

WitcherGeralt ★★
()
Ответ на: комментарий от PolarFox

И вообще, лучше храни значения в какой-нибудь БД

Спасибо. WitcherGeralt тоже это рекомендовал.

the1 ★★
()

Всем спасибо за советы.

Пока некогда, чуть позже хочу прикрутить в скрипт таймер, который раз в 5 сек будет смотреть размер и время правки ini-файла, и при переменах считывать из него новые параметры.

Novator ★★★★★
() автор топика

А зачем запускать nginx на винде? Хотя бы в докер запихни уже, или wsl установи.

Расширю ответ: у тебя таргет-платформа все равно линукс-коробка, пиши под нее, а не под удобство случайного разработчика. Засунь весь проект в докер и там уже делай, что хочешь.

А вообще да, это нужно делать программно из кода, а не ждать, что кто-то nginx перезапустит.

cdshines ★★★★★
()
Последнее исправление: cdshines (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.