首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >订阅反应性源的Python服务在对象中产生奇怪的行为。

订阅反应性源的Python服务在对象中产生奇怪的行为。
EN

Stack Overflow用户
提问于 2018-05-14 06:59:00
回答 1查看 313关注 0票数 10

我使用Falcon实现了一个web服务。此服务存储一个传递给构造函数中的服务资源的状态机 (pytransitions)。该服务与gunicorn一起运行。

web服务在开始时使用RxPy启动一个进程。on_next(event)中返回的事件用于触发状态机中的转换。

BUG

我希望状态机在服务和资源中都具有一致的状态,但是在资源中,状态似乎永远不会改变。

我们有一个尝试复制这种行为的测试,但令人惊讶的是,测试成功了。

代码语言:javascript
复制
class TochoLevel(object):

    def __init__(self, tochine):
        self.tochine = tochine

    def on_get(self, req, res):
        res.status = falcon.HTTP_200
        res.body = self.tochine.state


def get_machine():
    states = ["low", "medium", "high"]

    transitions = [
        {'trigger': 'to_medium', 'source': ['low', 'medium', 'high'], 'dest': 'medium'},
        {'trigger': 'to_high', 'source': ['low', 'medium', 'high'], 'dest': 'high'},
        {'trigger': 'to_low', 'source': ['low', 'medium', 'high'], 'dest': 'low'}
    ]

    locked_factory = MachineFactory.get_predefined(locked=True)

    return locked_factory(
        states=states,
        transitions=transitions,
        initial='low',
        auto_transitions=False,
        queued=False
    )

def _level_observable(observer):
    for i in range(1, 21):
        sleep(0.1)
        next_val = 'to_low'

        if 8 <= i <= 15:
            next_val = 'to_medium'
        elif i > 15:
            next_val = 'to_high'
        observer.on_next(next_val)

    observer.on_completed()

def get_level_observable():
    return Observable.create(_level_observable)

class NotBlockingService(falcon.API):
    def __init__(self):
        super(NotBlockingService, self).__init__()

        self.tochine = get_machine()
        self.add_route('/tochez', TochoLevel(self.tochine))

    def _run_machine(self, val):
        self.tochine.trigger(val)
        print('machine exec: {}, state: {}'.format(val, self.tochine.state))
        return self.tochine.state

    def start(self):
        source = get_level_observable()
        (source.subscribe_on(ThreadPoolScheduler(2))
            .subscribe(self._run_machine))


def test_can_query_falcon_service_while_being_susbcribed_as_observer():

    svc = NotBlockingService()
    client = testing.TestClient(svc)

    assert client.simulate_get('/tochez').text == 'low'

    start = time()
    svc.start()
    sleep(1.2)

    assert client.simulate_get('/tochez').text == 'medium'
    end = time()

    sleep(1.2)

    assert client.simulate_get('/tochez').text == 'high'
    assert (end - start) < 2

问题

当我使用TochoLevel启动服务并在rxpyon_next方法中传播状态时,状态机为什么不更改资源中的状态?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-14 08:11:02

当然,当您以开发模式执行您的服务时,您只使用一个分叉(一个执行过程)。当您使用像Gunicorn这样的软件时,您正在使用预分叉策略,以便在生产环境中提供可靠的服务。

预分叉策略产生多个子进程来解决请求,逻辑是独立的,在不同请求之间以独立模式工作。

由于Python中WSGI的标准化应用程序方案(佩普-333 & 佩普-3333),Gunicorn接收了一个应用程序对象。Gunicorn发布的实例(预叉)与其配置中显示的一样多。Gunicorn称这样的叉子工人和默认情况下,它使用1个工作人员。。每个工作人员将使用它的状态,也许Gunicorn也会为每个请求创建新的App对象实例.

这就是您的状态机背后没有持久性的原因。

提示:首先尝试用1名工作人员启动Gunicorn并检查状态机的状态持久性。如果您实现了状态机的持久性,则需要解决的第二个问题是沿所有工作人员的状态机同步。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50324645

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档