基础知识|线程与反应并发模型

时间:2015-03-15 23:56:52

标签: concurrency akka threadpool reactive-programming

我是反应式编程世界的全新手。我正在考虑将Akka Actors作为开始的一步。

我对基于线程的并发模型的理解是(例如基于Vanilla Servlet的模型):

  1. 对于来自客户端的每个请求,都会生成一个新线程。
  2. 这意味着所有底层代码的执行都附加到此线程并以串行方式发生。显然,即使代码的一部分存在瓶颈(远程Web服务调用等),线程也将被阻塞并等待并保持空闲状态。
  3. 服务器(容器)具有固定的线程池以容纳最大并发线程数,显然,由于瓶颈,它们将快速运行线程。
  4. 我对Reactive并发模型的理解是(例如基于Akka的模型):

    1. 所有逻辑不再附加到单个线程并以串行方式执行。
    2. 执行流程是被动的(即在消息上,一个actor被触发)。
    3. 现在我的问题:

      假设两个模型中都存在远程Web服务调用的瓶颈。 演员模型如何帮助提高CPU /核心利用率?我们不会有同样的问题,即演员中的执行线程被阻止了吗? 例如:如果此网络服务呼叫同时阻止了200名参与者?这不意味着目前有200个线程被阻止吗? 据我所知,还有其他演员会对其他上游事件做出反应。这是我们所说的更好地利用CPU吗?

      在一个Threaded模型中,只是Threadpool的小尺寸导致了问题吗?

      Actor子系统是否有一个线程池来产生一个新的actor并对特定事件作出反应?如果是,那么我们不会遇到同样的问题吗?

      请原谅我这个问题是完全愚蠢的。

2 个答案:

答案 0 :(得分:2)

“假设瓶颈......” - 在Reactive模型中,您永远不会使用此类服务​​,而是异步调用Web服务的请求,并为最终响应/错误配置处理程序。 如果您调用同步服务,则只是重新引入所有批处理模式问题,从而使您的问题更加复杂。如果你不能直接使用一个,你可以创建一个类似代理的服务作为苍白的模仿(*)。

当响应到达时,处理程序可以解开继续操作所需的任何上下文。如果所述上下文相当于“堆栈+寄存器”,那么你的框架不是很好,但是比拥有数百个内核线程上下文来解析消息更好。

必须构建响应上下文的形式主义应该引导解决方案摆脱对资源的争夺,这在线程模型中很常见。这是一个平局,因为如果反直觉,好的螺纹和差的反应解决方案都是可能的。

回顾:应用程序空间中的一个小数据结构,它包含继续操作所需的信息,比内核线程+用户线程+堆栈要好得多。不只是因为它使用的资源更少;但是因为它更好地表达了你的解决方案,并且允许底层框架/ os / kernel / ...根据比“返回地址”更多的信息对事件调度进行排序。

自然反应问题应该有自然反应的解决方案,正如自然批处理问题应该有自然的批处理解决方案。

(*)=几乎所有的反应式框架都是基于传统的同步内核构建的,例如linux;反应性内核正在发展,大型多处理器的到来将有助于将这些概念纳入主流。

答案 1 :(得分:2)

演员是否可以提供帮助可归结为演员如何实施。如果它们确实是单独的线程,那么未在Web服务上阻塞的actor将继续执行。因此,即使Web服务阻止其中一些工作,仍然可以继续进行有用的工作。

如果增加线程池的大小,也是如此。其中一些人将从事其他有用的工作。

拥有200个线程意味着您现在正在为底层操作系统带来更多负担。很多人会反应恐怖。但是,值得研究的是“操作系统的负担”究竟是什么。这是一点点记忆,就是这样。对于在Web服务上阻塞的线程,它们被阻塞,它们没有被调度,因此它们不会增加系统的上下文切换负担(上下文切换是性能杀手;在很多线程之间切换很多时间)。因此,它们对系统性能的影响相对较小(假设您没有动态生成Actors)。

因此,在这两种方法中,您需要足够的线程(Actors或线程池线程),以便有合理的数字使Web服务100%被利用,并且还有足够的其他任务来保持本地机器的忙碌。您只需要使两台机器都饱和,但不要让本地机器同时处理太多准备好的线程。

现在,每个网络,Web服务,主机都是不同的,性能是一个变化的东西。您最终将编写代码来动态控制线程池的大小或您准备启动的actor的数量。这可能很繁琐......