Периодическая выборка данных должна блокировать другие потоки, используя планировщик

Я новичок в питоне. Я благодарен за любую помощь. Итак, начнем.

Я использую приложение FLASK как API для отдыха. С каждым запросом возвращается JSON. Там может быть около 20 запросов в секунду. В фоновом режиме я использую APscheduler для получения фактических данных каждые 60 секунд из ldap.

scheduler = BackgroundScheduler()
scheduler.add_job(
    func=my_ldap.fetch_people_ldap,
    trigger=IntervalTrigger(seconds=60),
    id='fetching_data_job',
    name='Fetch data from ldap every 60 seconds')

scheduler.start()
atexit.register(lambda : scheduler.shutdown())

Но на самом деле, когда происходит обращение к datafetch с помощью вызова API, приложение закрывается из-за проблемы с памятью, я думаю, что это является причиной того, что я получаю доступ к объекту ldap одновременно fetch_people_ldap- функция вызывается планировщиком.

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

Есть ли какие-либо рекомендации или решения?

Это журнал, который я получаю за ошибку: Фатальная ошибка Python: сохранение потока дважды?

Thread 0x00007f95f3fff700 (most recent call first):
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 294 in _ldap_call
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 721 in result4
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 714 in result3
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 707 in result2
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 703 in result
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 796 in search_ext_s
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 802 in search_s
  File "/path/to/folder/tt_report_api/training_tool_report_api/sample/ldap_check/ldapCheck.py", line 49 in fetch_people_ldap
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/apscheduler/executors/base.py", line 125 in run_job
  File "/usr/lib/python3.5/concurrent/futures/thread.py", line 55 in run
  File "/usr/lib/python3.5/concurrent/futures/thread.py", line 66 in _worker
  File "/usr/lib/python3.5/threading.py", line 862 in run
  File "/usr/lib/python3.5/threading.py", line 914 in _bootstrap_inner
  File "/usr/lib/python3.5/threading.py", line 882 in _bootstrap

Thread 0x00007f95f8910700 (most recent call first):
  File "/usr/lib/python3.5/threading.py", line 297 in wait
  File "/usr/lib/python3.5/threading.py", line 549 in wait
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/apscheduler/schedulers/blocking.py", line 28 in _main_loop
  File "/usr/lib/python3.5/threading.py", line 862 in run
  File "/usr/lib/python3.5/threading.py", line 914 in _bootstrap_inner
  File "/usr/lib/python3.5/threading.py", line 882 in _bootstrap

Current thread 0x00007f9605505700 (most recent call first):
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 294 in _ldap_call
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 791 in search_ext
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 795 in search_ext_s
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 802 in search_s
  File "/path/to/folder/tt_report_api/training_tool_report_api/sample/ldap_check/ldapCheck.py", line 59 in check_node
  File "/path/to/folder/tt_report_api/training_tool_report_api/sample/ldap_check/ldapCheck.py", line 118 in build_tree_recursive
  File "/path/to/folder/tt_report_api/training_tool_report_api/sample/ldap_check/ldapCheck.py", line 124 in build_tree_recursive
  File "/path/to/folder/tt_report_api/training_tool_report_api/sample/ldap_check/ldapCheck.py", line 124 in build_tree_recursive
  File "/path/to/folder/tt_report_api/training_tool_report_api/sample/ldap_check/ldapCheck.py", line 129 in build_tree
  File "/path/to/folder/tt_report_api/training_tool_report_api/sample/app/app.py", line 83 in get_trainings_by_unit
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/flask/app.py", line 1598 in dispatch_request
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/flask/app.py", line 1612 in full_dispatch_request
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/flask/app.py", line 1982 in wsgi_app
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/flask/app.py", line 1997 in __call__
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/werkzeug/serving.py", line 197 in execute
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/werkzeug/serving.py", line 209 in run_wsgi
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/werkzeug/serving.py", line 267 in handle_one_request
  File "/usr/lib/python3.5/http/server.py", line 422 in handle
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/werkzeug/serving.py", line 232 in handle
  File "/usr/lib/python3.5/socketserver.py", line 681 in __init__
  File "/usr/lib/python3.5/socketserver.py", line 354 in finish_request
  File "/usr/lib/python3.5/socketserver.py", line 341 in process_request
  File "/usr/lib/python3.5/socketserver.py", line 313 in _handle_request_noblock
  File "/usr/lib/python3.5/socketserver.py", line 234 in serve_forever
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/werkzeug/serving.py", line 539 in serve_forever
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/werkzeug/serving.py", line 702 in inner
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/werkzeug/serving.py", line 739 in run_simple
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/flask/app.py", line 841 in run
  File "/path/to/folder/tt_report_api/training_tool_report_api/sample/app/app.py", line 92 in <module>

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)

1 ответ

Проблема в том, что ваш обработчик вызовов API также вызывает LDAP для создания ответа. Если вы будете получать 20 запросов в секунду, это вызовет проблемы. Запланированный звонок также не имеет особого смысла, потому что, когда вы используете полученные данные?

Мой подход заключается в том, чтобы запланированное задание обновляло общее хранилище данных в фоновом режиме. Тогда ваш вызов API только читает данные из этого общего хранилища данных и вообще не должен касаться LDAP. Используете ли вы базу данных или просто память, зависит от размера и сложности данных, с которыми вы работаете.

Главное состоит в том, чтобы отделить создание ответа API от извлечения данных из LDAP.

РЕДАКТИРОВАТЬ: я понимаю из вашего комментария, что вы думаете, что ваш API использует только ваш собственный код ldapCheck.py, но если вы посмотрите на трассировку полного стека, он на самом деле использует библиотеку LDAP для вызова:

API Thread:

Current thread 0x00007f9605505700 (most recent call first):
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 294 in _ldap_call
...
  File "/path/to/folder/tt_report_api/training_tool_report_api/sample/ldap_check/ldapCheck.py", line 124 in build_tree_recursive
...
File "/path/to/folder/tt_report_api/training_tool_report_api/sample/app/app.py", line 83 in get_trainings_by_unit
...
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/flask/app.py", line 841 in run

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

Thread 0x00007f95f3fff700 (most recent call first):
  File "/path/to/folder/virtual_env_1/lib/python3.5/site-packages/pyldap-2.4.37-py3.5-linux-x86_64.egg/ldap/ldapobject.py", line 294 in _ldap_call
...
  File "/path/to/folder/tt_report_api/training_tool_report_api/sample/ldap_check/ldapCheck.py", line 49 in fetch_people_ldap
...
  File "/usr/lib/python3.5/threading.py", line 882 in _bootstrap

Решение не состоит в том, чтобы заблокировать Ваш поток API. Решение состоит в том, чтобы убедиться, что код в ldapCheck.py", line 59 in check_node не обращается к вашей библиотеке LDAP, но использует информацию, уже извлеченную и сохраненную фоновым потоком.

Другие вопросы по тегам