播放框架运行长时间阻塞任务,而不阻塞客户端

Posted

技术标签:

【中文标题】播放框架运行长时间阻塞任务,而不阻塞客户端【英文标题】:Play framework running long blocking tasks, without blocking the client 【发布时间】:2016-04-14 18:25:14 【问题描述】:

Web客户端在等待响应时会被阻塞,但服务器上不会阻塞任何东西,服务器资源可以用来服务其他客户端。

某些客户端请求需要我的服务器执行长时间阻塞任务。我知道我可以在单独的线程池中执行它们。 但我也不希望客户端被阻止。我只想立即向客户端返回响应(例如,OK 得到你的厚长阻塞任务)。客户端并不关心获取任务执行的结果,它只需要知道我正在执行它。

如何在游戏中实现这种行为?

我想我可以创建一个作业队列并使用另一个线程来处理作业队列。其中播放控制器仅将作业添加到队列中,而另一个线程从队列中执行作业。我应该这样做吗?我应该使用 Akka 演员吗? (我不知道 Akka 我需要学习它)

【问题讨论】:

【参考方案1】:

回调

一切都始于回调。

你肯定看过这个:

Something.save(function(err)   
  if (err)  
    //error handling
    return;
  
  console.log('success');
);

这是在 javascript 中定义一个回调 - 将异步执行的东西。由于它们的语法、实现等等,回调并不是你真正的朋友。过度使用它们会导致可怕的回调地狱

承诺

在这种情况下:ES6 中的承诺

Something.save()  
  .then(function() 
    console.log('success');
  )
  .catch(function() 
    //error handling
  )

Promise 不是 'ES6 的东西',它们已经存在很多年了,ES6 将它们带给你。 Promise 很好,你甚至可以将它们链接起来:

saveSomething()  
  .then(updateOtherthing)
  .then(deleteStuff)  
  .then(logResults);

但对于疯狂的人来说,异步已经足够了。

WebSocket

WebSocket 是我推荐的东西:

截至今天very well supported Play 2.x 中的出色支持 全双工 TCP 你终于有时间学习 Akka 了;)

因此,您可以创建一个客户端来打开与 Play 应用程序的 WebSocket 连接。在服务器端,您可以handle WebSocket connections either with Akka actors(我推荐)或在流上使用回调。使用actors真的很简单也很有趣——你定义了一个actor——当有人打开一个WebSocket连接时,这个actor的一个实例就会产生,然后你在WebSocket通道中收到的每条消息都会被actor接收到——你可以专注于您的业务逻辑而无需考虑周围环境,然后将消息发送回去 - 这是 Akka 擅长的。

【讨论】:

以上是关于播放框架运行长时间阻塞任务,而不阻塞客户端的主要内容,如果未能解决你的问题,请参考以下文章

python的sched模块可​​以在任务执行期间不阻塞地运行异步任务吗?

java 多次new DataOutputStream而不关闭,线程阻塞

Javascript Promises库在浏览器中制作“长时间运行代码 - 非阻塞UI”?

向客户端发送有关视图中长时间运行任务的进度的更新

用于运行调度程序长时间运行任务的 Web Api 或 WCF

执行ALTER TABLE语句时如何避免长时间阻塞并发查询