dgo*_*sen 11 python rest design-patterns amqp flask
我正在处理一个python应用程序,它由多个分布式轻量级组件组成,这些组件使用RabbitMQ和Kombu进行通信.
组件侦听两个队列,并且可以在每个队列上接收多个消息类型.子类可以通过注册自定义处理程序来覆盖每种消息类型的处理方式.这一切都很好.
我现在有一个额外的要求,即每个组件必须具有基本的REST/HTML接口.您的想法是将浏览器指向正在运行的组件,并获取有关当前正在执行的操作的实时信息(处理的消息,CPU使用情况,状态信息,日志等)
它需要是轻量级的,所以经过一些研究我已经确定了Flask(但我愿意接受建议).在伪代码中,这意味着:
class Component:
Queue A
Queue B
...
def setup(..):
# connect to the broker & other initialization
def start(..):
# start the event loop and wait for work
def handle_msg_on_A(self,msg):
# dispatch a msg to a handler depending on the msg type
def handle_msg_on_B(self,msg):
...
...
Run Code Online (Sandbox Code Playgroud)
并添加了许多视图方法:
@app.route('/')
def web_ui(self):
# render to a template
@app.route('/state')
def get_state(self):
# REST method to return some internal state info as JSON
...
Run Code Online (Sandbox Code Playgroud)
但是,将Web UI固定到类似这样的类上会破坏SOLID原则并带来继承问题(子类可能希望显示更多/更少的信息).装饰器不是继承的,因此需要显式覆盖和重新装饰每个视图方法.也许使用mixin +反射可以以某种方式工作,但它感觉hackish.
相反,使用组合可以工作:将Web内容放在一个单独的类中,该类将url路由委托给嵌套组件上的一组固定的预定义多态方法.这样,组件仍然没有意识到Flask,但代价是灵活性有些损失(可用方法的集合是固定的).
我现在已经发现了Flask蓝图和Application Dispatching,看起来它们可以带来更好,更具扩展性的解决方案.但是,我还没有绕过它们.
我觉得我在这里错过了一个设计模式,希望有更多烧瓶或有这类问题经验的人可以发表评论.
Sea*_*ira 11
在Flask 0.7中悄悄地介绍了其他一些你可能感兴趣的东西 - Pluggable Views.这些是基于类而不是基于函数的端点 - 因此您可以使用该dispatch_request方法来管理状态转换(仅在需要时覆盖它).
与使用Application Dispatching相反,以这种方式执行此操作的好处是,您可以url_for在整个应用程序中获得支持(而不是必须在跨越应用程序边界的URL中进行硬编码.)您必须确定这是否是某些内容这可能是您的应用程序的问题.
在伪代码中:
# File: Components.py
from flask.views import View
class Component(View):
# Define your Component-specific application logic here
dispatch_request(self, *url_args, **url_kwargs):
# Define route-specific logic that all Components should have here.
# Call Component-specific methods as necessary
class Tool_1(Component):
pass
class Tool_2(Component):
# Override methods here
Run Code Online (Sandbox Code Playgroud)
# File: app.py
from flask import Flask
from yourapplication import Tool_1, Tool_2
app = Flask()
# Assuming you want to pass all additional parameters as one argument
app.add_url_rule("/tool_1/<path:options>", "tool1", view_func=Tool_1.as_view())
# Assuming you want to pass additional parameters separately
tool_2_view = Tool_2.as_view()
app.add_url_rule("/tool_2/", "tool2", view_func=tool_2_view )
app.add_url_rule("/tool_2/<option>", "tool2", view_func=tool_2_view)
app.add_url_rule("/tool_2/<option>/<filter>", "tool2", view_func=tool_2_view)
Run Code Online (Sandbox Code Playgroud)
如果您有一系列逻辑上连接在一起的组件,并且您不想记得在每个人的呼叫前面放置,那么您可以在混音中添加蓝图.但如果你只是有一系列的组件大多是相互独立的,这是我应该使用模式*./prefixadd_url_rule
*.另一方面,如果它们需要彼此隔离,我将使用文档中推荐的应用程序调度模式.
| 归档时间: |
|
| 查看次数: |
8798 次 |
| 最近记录: |