我有一个长期运行的后台任务,它将再次旋转Flask应用程序并在后台进行一些审核。前端是一个Web应用程序,并使用socketio与后端主烧瓶应用程序进行通信,以处理多种异步行为。
我确保仅在创建主线程时才触发后台任务,并且仅在脚本的开头执行eventlet.monkey_patch()
。
如果后台线程有很多要审核的内容,则它将阻塞主线程,内存中的内容越多,则阻塞主线程的时间就越长。审计根本不占用CPU,只是一些数据库插入和日志记录。
sleep(2)
时,没有任何阻塞。
import eventlet
eventlet.monkey_patch()
# ... rest of code is a basic flask app create_app factory that at some # point starts the new thread if it's the main thread
# the async code that runs is the following
class AsyncAuditor(threading.Thread):
def __init__(self, tasks: list, stop: threading.Event):
super().__init__()
self.tasks = tasks
self.stop_event = stop
def run(self):
from app import init_app
from dal import db
app = init_app(mode='sys')
app.logger.info('starting async audit thread')
with app.app_context():
try:
while not self.stop_event.is_set():
if len(self.tasks) > 0:
task: dict
for task in self.tasks:
app.logger.debug(threading.current_thread().name + ' new audit record')
task.payload = encryptor.encrypt(task.payload)
task.ip = struct.unpack("!I", socket.inet_aton(task.ip))[0]
db.session.add(task)
self.tasks.clear()
db.session.commit()
sleep(2)
app.logger.info('exiting async audit thread')
except BaseException as e:
app.logger.exception('Exception')
# there's some code that tries to gracefully exit if app needs to exit
stop_event = threading.Event()
async_task = AsyncAuditor(API.audit_tasks, stop_event)
async_task.start()
def exit_async_thread():
stop_event.set()
async_task.join()
atexit.register(exit_async_thread)
我希望在子线程工作时,主线程不会被任何db操作阻塞,实际上,就像我之前提到的那样,如果我没有猴子补丁事件子集,那么在主线程中一切正常还有一个孩子取而代之的是,当后台任务正在运行时,在烧瓶应用程序中命中端点时,我得到了9甚至30秒的延迟。