Play WebSockets 是否支持背压?

Do Play WebSockets support back-pressure?

我需要向我的 Play 2.3 应用程序添加一个 WebSocket 到 TCP 代理,但是虽然使用 Akka I/O 的传出 TCP 连接支持背压,但我没有看到任何 WebSocket 的内容。基于 actor 的 API 显然不支持,但是 James Roper says:

Iteratees handle this by design, you can't feed a new element into an iteratee until last future it returns has been redeemed, because you don't have a reference to it until then.

但是,我不明白他指的是什么。 Iteratee.foreach,在示例中使用,似乎太简单了。我在 iteratee API 中看到的唯一未来是完成计算结果。我应该为每条消息完成 Future[Unit] 还是什么?

IterateeIterator 不同。 Iteratee 确实固有地支持背压(事实上你会发现自己遇到了相反的问题 - 默认情况下它们不做任何缓冲(至少在管道内 - 当然异步套接字仍然有接收缓冲区),因此有时您必须向 enumerator/iteratee 管道添加显式缓冲步骤才能获得合理的性能)。这些示例看起来很简单,但这仅意味着框架正在做框架所做的事情并使事情变得简单。如果您在处理程序中执行大量工作或进行异步调用,则不应使用简单的 Iteratee.foreach,而应使用接受 [=14= 的 API基于]的处理程序;如果您在 Iteratee 内阻塞,那么您会阻塞整个事情,浪费您的线程,并且完全没有使用它们的意义。

Iteratee.foldM 允许将一个状态传递给每个步骤,就像常规的折叠操作一样,return 一个未来。如果你没有这样的状态,你可以只传递 Unit 并且它将表现为一个 foreach,在未来完成之前不会接受下一步。

下面是一个效用函数的例子,它完全可以做到这一点:

 def foreachM[E](f: E => Future[Unit])(implicit ec: ExecutionContext): Iteratee[E, Unit] = 
   Iteratee.foldM[E, Unit](Unit)((_, e) => f(e))