Форум сайта python.su
привет всем.
помогите, чем можете
есть приложение (сервис на фласк/юникорн), в нём два модуля:
1) модуль, содержащий сервисный рест-метод, постоянно держащий в памяти гигабайтный файл для работы с ним (читает файл при импорте модуля);
2) модуль-“синглтон” (по крайней мере на жабе он им бы и был), в котором есть бакграундная функция, которая сливает лог запросов в sql.
время ответа сервиса очень критично, а sql жутко тормозной, потому лог-функцию завернул в @deco.concurrent и так и пользую (дабы не ждать результатов её исполнения, ибо это мне фиолетово).
но есть, зараза, нюанс: процесс, в котором висит лог-функция, занимает тоже гиг.
вот тут я слегка (от слова совсем) не понимаю процессную механику питона. как я подозреваю, он либо параллелит уже проинициализированный экземпляр приложения (т.е. то, что находит в памяти при, грубо говоря, первом вызове функции лога), либо же инитит целиком всё приложение при создании нового экземпляра процесса с этим несчастным логом.
этот самый лишний гиг информации логу нужен как пятая нога, а ресурсы жрёт-с.
собственно, вопрос - как построить приложение таким образом, чтобы “мухи отдельно, котлеты отдельно”? т.е. чтоб сервис (блупринт-модуль) жрал бы свой гиг и работал с ним, а процесс с лог-функцией (соседний модуль, но к которому обращается сервис) об этом файле даже бы не знал? сие вообще возможно, или при инициализации параллельного процесса инитится вообще всё, начиная с “файла запуска”?
весь мозг уже сломал, не понимаю, куда копать. ткните хотя бы чего почитать на эту тему.
Офлайн
zartyдумаю вам надо посмотреть для чего пишут
ткните хотя бы чего почитать на эту тему
Офлайн
doza_and
Офлайн
zarty
а все остальные инициализации делать ленивыми?
Офлайн
doza_and
По сути да. Приведите прототип вашего кода.
from modules.big_file import do_file
app = flask.Flask(...)
@app.route('/<path>')
def get_info(path):
return do_file(path)
from modules.sql import do_log
_info_file = None
def do_file(path):
do_log(f'запросили {path}')
return вернуть_инфу_из_файла(_info_file, path)
def _preload_file():
global _info_file
_info_file = загрузить_большой_файл()
_preload_file()
import deco
#результат выполнения этой функции вообще не интересует, и она должна быть в другом процессе
@deco.concurrent(processes=1)
def do_log(text)
запихнуть_текст_в_sql(text)
Отредактировано zarty (Янв. 31, 2018 14:18:53)
Офлайн
zartyНе большой спец по этим вопросам. Но посоветую смотреть не в сторону жалкого лога а в сторону gunicorn. Насколько я понимаю он создает пул процессов для обработки сообщений. У вас в каждом процессе будет по экземпляру файла. Хорошо что их пока только два экземпляра.
в коде там нечто такое (работает под gunicorn):
Офлайн