我有一个Flask微服务,可以为端点提供用户请求(比如说):/getdata
数据可以通过以下两种方式之一获取:1)缓存或2)直接从数据库获取 - 如果缓存正在更新中
另一项服务更新数据库(从而使缓存失效)。一旦服务更新完成数据库,它就会向rabbitmq发布一条消息:“update done”
回到微服务:我希望它有两个线程:
线程1:运行app.run()
线程2:订阅队列 - 发布“更新完成”消息
鉴于这两个线程,我不希望/getdata
在更新时从缓存中获取数据库。同时,我不想在从端点获取数据时更新缓存。
这是我能想到的一个解决方案:
1)将threading.Lock()
作为“全球”
2)/getdata
检查锁是否可用;如果是这样,它将获取,从缓存中获取数据并释放锁。如果锁不可用,它将直接从数据库中获取数据,从而导致性能损失 - 但仍然获得“最新”数据
3)RabbitMQ“subscriber”检查锁的状态;如果是这样,它获取锁,从数据库更新缓存并释放锁。如果没有,它会将请求添加到本地“队列”,并在尝试再次获取锁之前等待一分钟。如果是,它将从队列中弹出第一个项目并从数据库更新缓存。
我的问题:
鉴于Python / Flask中的众多库和选项 - 是
有一个图书馆,允许我以“安全”的方式完成这样的任务
(我正在使用pika
进行rabbitmq访问)
是否可以通过一个线程启动烧瓶app.run()
通过另一个队列订阅用户(即在if __name__ == "main"
中:
)
注意:
我希望在更糟糕的情况下,锁定不会超过一分钟。
答案 0 :(得分:3)
Pika不是线程安全的。您应该避免在Flask的上下文中共享连接对象。编写自己的Flask插件不会占用那么多样板。它与the documentation example plugin非常相似。否则,您可以在搜索引擎上使用flask pika
进行快速搜索,然后您会找到一些用于此目的的现有插件。我没有试过它们,它们似乎不太受欢迎,但也许你应该给它们一个去吧?
我不明白为什么不可能。 Flask知道如何处理这个问题。但是,我认为它会严重降低性能。此外,如果你使用的插件写得不完整,你可能会碰到一些角落。
就像你要为线程声明任何锁定一样。没什么。你把它放在模块级别(不是在Flask的上下文中),这样它就是全局的,就是这样。
话虽如此,我认为你不应该这样做。您应该在与Web服务器不同的进程中运行update-job(如果需要重新使用某些函数,则使用Flask CLI或其他任何操作)。这将是更好的性能,它更容易推理,它更松散耦合。
此外,您应该尽可能避免遇到锁定头痛。相信我,这是一个真正的问题来源。在实际生产用例中,正确测试,调试,维护和风险很大,这是一场噩梦。如果你真的需要锁定,不要持有它一分钟,这太长了。
我不知道您的确切要求,但肯定有一个解决方案是可以的,并且不会涉及这种复杂性。