Flask-sqlalchemy uwsgi。使用多个进程时的DB连接问题

问题描述 投票:0回答:1

我有一个Flask应用在Heroku上运行,有uwsgi服务器,其中每个用户都连接到自己的数据库。我已经实现了 类似情况的解决方案. 特别是,我实现了如下的连接注册表。

class DBSessionRegistry():
    _registry = {}

    def get(self, URI, **kwargs):
        if URI not in self._registry:
            current_app.logger.info(f'INFO - CREATING A NEW CONNECTION')
            try:
                engine = create_engine(URI,
                                       echo=False,
                                       pool_size=5,
                                       max_overflow=5)
                session_factory = sessionmaker(bind=engine)
                Session = scoped_session(session_factory)
                a_session = Session()
                self._registry[URI] = a_session
            except ArgumentError:
                raise Exception('Error')

        current_app.logger.info(f'SESSION ID: {id(self._registry[URI])}')
        current_app.logger.info(f'REGISTRY ID: {id(self._registry)}')
        current_app.logger.info(f'REGISTRY SIZE: {len(self._registry.keys())}')
        current_app.logger.info(f'APP ID: {id(current_app)}')

        return self._registry[URI]

在我的 create_app() 我给应用程序分配了一个注册表。

app.DBregistry = DBSessionRegistry()

每当我需要和数据库对话时,我就会调用。

current_app.DBregistry.get(URI)

其中 URI 是依赖于用户的。如果我在一个进程中使用uwsgi,这很好用。对于更多的进程。

[uwsgi]
processes = 4
threads = 1

有时它会卡在一些请求上,返回一个503错误代码。我发现这个问题出现在uwsgi的不同进程处理请求的时候。这是日志的摘录,我对其进行了注释以说明问题。

# ... EVERYTHING OK UP TO HERE.
# ALL PREVIOUS REQUESTS HANDLED BY PROCESS pid = 12
INFO in utils: SESSION ID: 139860361716304
INFO in utils: REGISTRY ID: 139860484608480
INFO in utils: REGISTRY SIZE: 1
INFO in utils: APP ID: 139860526857584
# NOTE THE pid IN THE NEXT LINE...
[pid: 12|app: 0|req: 1/1] POST /manager/_save_task => 
generated 154 bytes in 3457 msecs (HTTP/1.1 200) 4 headers in 601 
bytes (1 switches on core 0)
# PREVIOUS REQUEST WAS MANAGED BY PROCESS pid = 12
# THE NEXT REQUEST IS FROM THE SAME USER AND TO THE SAME URL.
# SO THERE IS NO NEED FOR CREATING A NEW CONNECTION, BUT INSTEAD...
INFO - CREATING A NEW CONNECTION
# TO THIS POINT, I DON'T UNDERSTAND WHY IT CREATED A NEW CONNECTION.
# THE SESSION ID CHANGES, AS IT IS A NEW SESSION
INFO in utils: SESSION ID: 139860363793168    # <<--- CHANGED
INFO in utils: REGISTRY ID: 139860484608480
INFO in utils: REGISTRY SIZE: 1
# THE APP AND THE REGISTRY ARE UNIQUE
INFO in utils: APP ID: 139860526857584
# uwsgi GIVES UP...
*** HARAKIRI ON WORKER 4 (pid: 11, try: 1) ***
# THE FAILED REQUEST WAS MANAGED BY PROCESS pid = 11
# I ASSUME THIS IS WHY IT CREATED A NEW CONNECTION
HARAKIRI: -- syscall> 7 0x7fff4290c6d8 0x1 0xffffffff 0x4000 0x0 0x0 
0x7fff4290c6b8 0x7f33d6e3cbc4
HARAKIRI: -- wchan> poll_schedule_timeout
HARAKIRI !!! worker 4 status !!!
HARAKIRI [core 0] - POST /manager/_save_task since 1587660997
HARAKIRI !!! end of worker 4 status !!!
heroku[router]: at=error code=H13 desc="Connection closed without 
response" method=POST path="/manager/_save_task"
DAMN ! worker 4 (pid: 11) died, killed by signal 9 :( trying respawn ...
Respawned uWSGI worker 4 (new pid: 14)
# FROM HERE ON, NOTHINGS WORKS ANYMORE

这种行为在几次尝试中都是一致的:当pid改变时,请求失败。即使有一个 pool_size = 1create_engine 函数,问题依然存在。没有问题,反而是uwsgi被用在一个进程上。

我很确定这是我的错,有一些我不知道的东西,或者我不了解uwsgi和sqlalchemy的工作方式。你能不能帮帮我?

谢谢你的帮助

flask heroku sqlalchemy flask-sqlalchemy uwsgi
1个回答
1
投票

遇到的情况是你正在尝试在进程之间共享内存,这些帖子中有一些解释。

(是否可以在运行flask应用的uwsgi进程之间共享内存?).

(https:/stackoverflow.coma4538361711542053。)

你可以使用一个额外的层来存储你在应用程序之外的会话。

为此,你可以使用 uWsgi 的 SharedArea(https:/uwsgi-docs.readthedocs.ioenlatestSharedArea.html。),这是非常低级的,或者你可以使用其他方法,比如uWsgi的缓存(https:/uwsgi-docs.readthedocs.ioenlatestCaching.html。)

希望对你有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.