Play framework 运行 长阻塞任务,不阻塞客户端

Play framework running long blocking tasks, without blocking the client

The web client will be blocked while waiting for the response, but nothing will be blocked on the server, and server resources can be used to serve other clients.

一些客户端请求需要我的服务器执行长时间阻塞任务。我明白我可以在一个单独的线程池中执行它们。
但我也不希望客户端被阻止。我只想 return 立即响应客户端(例如,好的,你的粗长阻塞任务)。客户端不关心获取任务执行的结果,它只需要知道我正在执行它。

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

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

回调

一切都从回调开始。

你肯定看过这个:

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

这是在 JavaScript 中定义回调 - 将异步执行的内容。由于它们的语法、实现和诸如此类的东西,回调并不是你真正的朋友。过度使用它们会导致可怕的 回调地狱

承诺

在此上下文中:ES6 中的 Promises

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

Promises 不是 'ES6-thing',它们已经存在多年,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 (我推荐)或在流上使用回调。使用 actor 真的很简单也很有趣——你定义一个 Actor——当有人打开一个 WebSocket 连接时,这个 actor 的一个实例就会被生成,然后你在 WebSocket 通道中收到的每条消息都会被这个 actor 接收——你可以专注于您的业务逻辑而无需考虑周围环境,然后将消息发回 - 这是 Akka 擅长的。