如何在WSGIServer / flask环境中同步gevent中的greenlet

时间:2016-10-23 00:29:24

标签: python flask raspberry-pi gevent greenlets

在我的基于烧瓶的http服务器设计用于远程管理RPI上的一些服务我接近了一个我无法单独解决的问题,因此请求你给我一个提示。

概念: 通过flask和gevent我可以停止并运行在RPI上运行的一些(两个)服务。我使用gevent和服务器端事件来尊重javascript以便收听html更新。

html页面显示服务的状态(开/关/处理),并提供打开/关闭它们的按钮。另外显示一些系统参数(CPU,RAM,HDD,NET)。

只要打开一个用户/页面,一切都可以正常工作。只要有更多用户访问烧瓶服务器,就会在每个用户/页面之间进行一次竞赛,并且不会重新加载所有页面。

问题: 如何向所有正在运行的greenlets sse_worker()发送消息并在常规作业之上处理它?<​​/ p>

高级代码下方。完整的源代码可以在这里找到:https://github.com/petervflocke/flasksse_rpi检查sse.py文件

def sse_worker(): #neverending task
   while True:
       if there_is_a_change_in_process_status:
          reload_page=True
       else: 
          reload_page=False
       Do some other tasks:
          update some_single_parameters_to_be_passed_to_html_page
       yield 'data: ' + json.dumps(all_parameters)
       gevent.sleep(1)

@app.route('/stream/', methods=['GET', 'POST'])
def stream():
    return Response(sse_worker(), mimetype="text/event-stream")

if __name__ == "__main__":
    gevent.signal(signal.SIGTERM, stop)
    http_server = WSGIServer(('', 5000), app)
    http_server.serve_forever()

...在html页面上,相应地处理流式json数据。如果服务状态已根据reload_page变量更改,则javascript会重新加载完整页面 - 代码提取如下:

<script>
    function listen() {
        var source = new EventSource("/stream/");
        var target1 = document.getElementById("time");
        ....  
        source.onmessage = function(msg) {
          obj = JSON.parse(msg.data);
          target1.innerHTML = obj.time;
        ....
          if (obj.reload == "1") {
            location.reload();
          }
        }
    }
    listen();
</script>

我想要的解决方案是扩展sse_worker(),如下所示:

def sse_worker():
   while True:
       if there_is_a_change_in_process_status:
          reload_page=True
          # NEW: set up a semaphore/flag that there is a change on the page
          message_set(reload)
       elif message_get(block=false)==reload: # NEW: check the semaphore
          # issue: the message_get must retun "reload" for _all_ active sse_workers, that all of them can push the reload to "their" pages 
          reload_page=True
       else: 
          reload_page=False
       Do some other tasks:
          update some_single_parameters_to_be_passed_to_html_page
       yield 'data: ' + json.dumps(all_parameters)
       gevent.sleep(1)

我希望我可以传递我的信息。在你身边有什么想法可以解决同步问题吗?请注意,我们在同一个sse_worker函数中有生产者和消费者。

非常欢迎任何想法! 最好的祝福 彼得

0 个答案:

没有答案