我正在尝试执行从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启动long_running_job_code并以setInterval的形式返回执行循环:
在客户端上的"循环":
setInterval(function() { pinger() }, 1000);
function pinger()
{
socket.emit('ping','test');
}
在服务器上:
@socketio.on('ping', namespace='/namespace')
def ping(message):
emit('my response', {'data': '.'})
在点击提交按钮之前,"ping"功能正在放置....但在long_running_job_code执行时它不会继续执行该功能。
我相信问题是在服务器端阻塞,但我不确定。 长时间运行的作业具有仍在到达客户端的发出,但 ping 发出在长时间运行的作业进行时停止。
有人知道如何解决这个问题吗?
谢谢!
你没有提到这一点,但我的猜测是你正在使用eventlet或gevent作为应用程序的Web服务器,因为这在使用WebSocket和Flask-SocketIO时最有意义。
Eventlet 和 gevent 是协程服务器。他们可以处理多任务处理,但这是合作完成的。这意味着要使上下文从一个任务切换到另一个任务,第一个任务必须释放 CPU。当进行某些 I/O 调用时,CPU 会自动透明地释放,例如从套接字读取或写入时。您还可以通过调用 sleep
函数来显式释放 CPU。如果一个任务在没有执行任何I/O或显式释放CPU的情况下进行一些长时间的计算,那么整个事情就会阻塞。
在运行长函数时,您基本上有两种方法可以保持机器运行。一种方法是定期拨打睡眠电话。当发生睡眠调用时,调度程序将在从睡眠状态返回之前将 CPU 提供给其他任务。例如,如果您的函数有一个循环,您可以在每次迭代时添加以下内容:
eventlet.sleep(0)
另一种不阻塞的方法是将长函数放在一个子进程中,这可能需要更多更改,只是在这里和那里添加睡眠。
希望这有帮助!