如何解决Websocket调用阻塞其他Websocket调用问题

3
我正在尝试从websocket客户端向服务器(python/flask/socketio)发送常量消息。
我在一个简单页面上有一个提交按钮,可以启动长时间运行的作业。
$('form#emit').submit(function(event) {
            socket.emit('submit', {...});
            return false;

在Python代码中,我这样启动长时间运行的作业:
@socketio.on('submit', namespace='/namespace')
def long_running_function(message):
    long_running_job_code(message)

我希望发生的是Python启动长时间运行的作业代码,然后返回执行间隔为setInterval的循环:
在客户端上的“loop”:
setInterval(function() { pinger() }, 1000);
    function pinger()
    {
       socket.emit('ping','test');
    }

在服务器上:
@socketio.on('ping', namespace='/namespace')
def ping(message):
    emit('my response', {'data': '.'})

在提交按钮被点击之前,“ping”函数会在屏幕上放置...,但它不会在长时间运行的作业代码执行时继续执行该函数。
我认为问题是在服务器端阻塞,但我不确定。长时间运行的作业仍然有发射到客户端,但 ping 发射在长时间运行的作业进行时停止了。
有人有想法如何解决这个问题吗?
谢谢!

你指的是哪个循环?我没有看到任何循环。你的问题是在服务器端还是客户端阻塞? - Ryan O'Donnell
在这种情况下,“loop”是setInterval(function()…它每1000毫秒发出一个ping。 - user1601716
在长时间运行的作业完成后,发生的 ping 发射被转储到屏幕上,因此它似乎将它们缓冲直到长时间运行的作业完成。目标是同时完成这两个操作。 - user1601716
1个回答

4
您没有提到这一点,但我猜测您正在使用eventlet或gevent作为应用程序的Web服务器,因为在特定于WebSocket和Flask-SocketIO的情况下,这是最明智的选择。Eventlet和gevent都是协程服务器。它们可以处理多任务,但这是通过协作完成的。这意味着,要从一个任务切换到另一个任务,第一个任务必须释放CPU。当进行某些I/O调用(例如从套接字读取或写入数据)时,CPU会自动透明地释放。您还可以通过调用“sleep”函数来显式释放CPU。如果一个任务在没有进行任何I/O或显式释放CPU的情况下进行了长时间计算,那么整个过程将会被阻塞。基本上,您有两种方法在运行长时间函数时保持机器运转。一种方法是定期发出sleep调用。当休眠调用发生时,在返回休眠之前,调度程序将把CPU分配给其他任务。如果您的函数具有循环结构,您可以在每次迭代中添加此操作:
eventlet.sleep(0)

另一种不阻塞的方法是将长函数放入子进程中,这可能需要更多的改变,而不仅仅是在这里添加睡眠时间。
希望这可以帮助你!

你说得对,我正在使用flask-socketIO,这为我提供了一些线索,我可以进行更多的实验来看如何最好地处理它。 - user1601716

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接