为什么我会选择基于线程/进程的方法与异步Web服务器

时间:2012-10-16 22:00:03

标签: multithreading asynchronous webserver multiprocessing

随着我对Web服务器软件的更多研究,我开始怀疑Apache的基于线程/进程的方法是否可以采用Nginx和Lighttpd等服务器提供的异步请求处理方式。在负载较重的情况下倾向于更好地扩展。

据我所知,后两者与Apache之间存在许多其他差异。我的问题是在什么情况下我会选择基于线程/进程的方法来进行异步处理。

  1. 是否有任何我不能使用异步方法的功能/技术(或功能不佳/不良)?

  2. 哪种情况会导致异步方法的性能比基于线程/进程的方法更差?这些是常见的还是罕见的情况,差异有多大?

  3. 比较两者时是否还有其他因素需要考虑?请记住,我主要关注基于线程/进程的方法与异步,而不是任何特定的服务器软件碰巧使用这些方法之一。这些问题可能是管理/调试困难,安全问题等。

2 个答案:

答案 0 :(得分:3)

这是旧的,但值得回答。让我们先说说每个模型是如何工作的。

在线程中,您有一个请求进入处理程序,处理程序产生一个新的OS线程来处理该请求,并且该请求的所有工作都发生在该线程中,直到发送响应并且线程结束。此模型支持与服务器可以生成的线程一样多的并发请求(但线程可能有点重量级)。

当执行异步时,请求进入处理程序但不是创建一个线程来处理它,而是将连接添加到所谓的事件循环。事件循环侦听连接上的数据/状态更改,并每次触发回调#34;某事情"发生。将连接添加到事件循环后,处理程序会立即侦听要添加的新连接。这允许您同时拥有许多(有时是100K)并发连接

  

我是否可以使用异步方法使用任何功能/技术(或者功能不佳/不良)?

是的,当你进行数字运算时。 async(或" evented")系统的体系结构非常适合传递数据但不能处理数据。它可以处理数千个并发操作,但由于它只在一个OS线程上运行,因此它需要尽可能少地执行回调以获得最大吞吐量。这是因为如果你的一个回调进行了一次需要5秒钟的数字运算,那么整个服务器将被冻结5秒直到该操作完成。我们的想法是获取数据,将数据发送到它所在的位置(数据库,API等)并以最少的处理发送响应。

Async适用于网络I / O:在多个源/目的地之间传递数据(以及用户界面,但超出此帖子)。

  

哪种情况会导致异步方法的性能比基于线程/进程的方法更差?这些是常见的还是罕见的情况,差异有多大?

见上文,但是每当您执行比网络I / O更多的CPU工作时,您应该切换到线程模型。但是,有架构解决方法...例如,您可以拥有一个异步应用程序,并且只要它需要执行实际工作,它就会将作业发送到工作队列。但是,如果每个请求都需要CPU处理,那么该架构就太过分了,您也可以使用线程服务器。

  

比较两者时是否还有其他因素需要考虑?请记住,我主要关注基于线程/进程的方法与异步,而不是任何碰巧使用这些方法之一的特定服务器软件。这些问题可能是管理/调试,安全问题等方面的困难。

异步编程通常比线程更复杂。也就是说,如果你自己没有进行编程(即你在nginx和apache之间进行选择),那么我通常建议你去async(nginx),因为你通常可以挤出更多的果汁以这种方式离开你的服务器。我总是赞成在堆栈中使用尽可能多的同步。

也就是说,如果您正在编写应用程序并尝试决定是使用线程模型还是异步模型,则必须考虑开发人员的时间。除非您在事件循环中使用具有绿色线程的语言(如方案),否则期望将您的头发撕掉,而不是流氓异常会使您的整个应用程序崩溃,并且通常会绕过CPS /使用回调的一切。期货/承诺是你的朋友,但只是一个让异步更好的乐队。

TL; DR

Async,当在服务器中使用时,如果您正在进行网络IO而不是其他任何,则可以挤出(很多)并行操作而不是线程

如果您正在进行任何类型的数字运算,请使用线程应用服务器使用带背景排队系统的异步应用。

除非你的语言支持"假的"否则Async很难编程。穿过它(即绿色线程)。一旦你越过了最初的驼峰,你通常会很好。如果你没有绿色线程,请使用promises。

如果您可以在线程和异步之间选择堆栈中的组件(apache vs nginx),并且它们提供完全相同的功能,则稍微偏爱异步。不要选择它,因为你认为它会使所有东西都快20倍。

答案 1 :(得分:0)

与线程和与安全性和可靠性相关的异步模型相比,进程具有多个优势。大多数网站不需要这些特殊优势,但有时候它们是不可或缺的。

  1. 安全性:您可以作为低权限用户在沙箱中运行工作进程,并且每个工作进程只处理一个请求。这可以缓解某些类型的安全漏洞:即使攻击者接管了您的整个工作进程,只要您根据请求元数据对其进行沙盒化(即它没有对所有数据的写访问权限),那么它就可以'损害系统稳定性或影响对请求的响应。
  2. 安全性#2:有时您需要对不受信任的代码进行沙箱化,或者强制执行不同代码或不同请求之间的隔离,而实现此目的的唯一方法是使用单独的一次性过程。 (想想运行用户提供的代码。)
  3. 可靠性:如果您经常(或针对每个请求)拆卸和替换工作进程,内存泄漏和内存损坏严重得多。
  4. 很容易对在单独进程中处理用户请求所花费的CPU时间,磁盘和网络配额等实施硬限制。即使请求处理代码进入无限循环,主进程(或操作系统)也可以强制执行超时。