基础 | 线程化 vs 响应式并发模型

9
我是一个完全的响应式编程新手。我正在研究Akka Actors作为开始尝试。
我对基于线程的并发模型的理解是(例如基于Vanilla Servlet的模型):
1. 对于来自客户端的每个请求,都会生成一个新线程。 2. 这意味着所有底层代码的执行都附加到此线程上并按顺序发生。显然,即使代码的某个部分有瓶颈(远程Web服务调用等),线程也会被阻塞、等待和保持空闲。 3. 服务器(容器)具有固定的线程池以容纳最大数量的并发线程,显然,由于瓶颈,它们将很快耗尽线程。
我对响应式并发模型的理解是(例如基于Akka的模型):
1. 所有逻辑不再附加到单个线程上并按顺序执行。 2. 执行流是响应式的(即在消息上,actor会被触发)。
现在我的问题是:
假设远程Web服务调用的瓶颈存在于这两种模型中。 演员模型如何帮助更好地利用CPU / Core?我们不会遇到演员内的执行线程被阻止的相同问题吗? 例如:如果有200个演员同时被此Web服务调用阻塞,这不意味着当前有200个线程被阻塞吗? 我知道仍然会有其他演员对其他上游事件做出反应。这是我们所称的更好地利用CPU吗?
在线程模型中,只有线程池的小规模是问题的原因吗?
Actor子系统是否具有线程池来生成新的actor并对特定事件做出反应?如果是,那么我们不会遇到相同的问题吗?
如果我的问题很愚蠢,请原谅。
2个回答

2
在反应式模型中,您永远不会使用这样的服务,而是会异步调用一个Web服务的请求,并配置一个处理程序来处理最终的响应/错误。如果您调用同步服务,则只会重新引入所有批处理问题,从而使问题更加复杂。如果您不能直接使用一个服务,您可以创建一个代理类似的服务作为苍白的模仿。
当响应到达时,处理程序可以展开所需的上下文以继续操作。如果该上下文量相当于“堆栈+寄存器”,那么您的框架并不是很好,但比拥有数百个内核线程上下文来解析消息要好得多。
必须构造响应上下文的形式主义应指导解决方案远离资源争夺,如线程模型中常见的那样。这是一种平衡,因为良好的线程和反应性解决方案都是可能的,尽管有些反直觉。
总之,在应用程序空间中保存必要信息以继续操作的小数据结构比内核线程+用户线程+堆栈要好得多。这不仅因为它使用的资源更少,而且因为它更好地表达了您的解决方案,并允许底层框架/操作系统/内核/...基于比“返回地址”更多的信息来序列化事件分派。
自然反应式问题应该有自然反应式解决方案,就像自然批处理问题应该有自然批处理解决方案一样。
(*)= 几乎所有反应式框架都建立在传统的同步内核(如Linux)之上;反应式内核正在发展,大型多处理器的到来将有助于推广这些概念。

2
演员是否有帮助取决于演员的实现方式。如果它们确实是单独的线程,那么没有被Web服务阻塞的演员将继续执行。因此,即使Web服务阻塞了其中一些演员,也会继续进行有用的工作。
如果增加线程池的大小,则其中一些线程将执行其他有用的工作。
拥有200个线程意味着你现在正在给底层操作系统增加更多负担。很多人会感到恐慌。然而,值得检查的是,“对操作系统的负担”实际上只是一点点内存而已。对于被Web服务阻塞的线程,它们被阻塞了,它们没有被调度,因此它们不会增加系统的上下文切换负担(上下文切换是性能杀手;在许多线程之间切换会消耗大量时间)。因此,它们对系统性能造成的损害相对较小(前提是您没有动态生成演员)。
因此,在这两种方法中,您需要足够多的线程(无论是演员还是线程池线程),以便有合理数量的线程保持Web服务100%利用率,并且有足够多的线程执行其他任务,以使本地机器也保持繁忙状态。您需要足够多的线程来饱和两台计算机,但不要让本地机器同时处理过多的准备好的线程。
现在,每个网络、Web服务、主机都是不同的,性能也是一个不断变化的事情。您最终会编写代码来动态控制线程池的大小或您愿意启动的演员数量。这可能有些麻烦...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接