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

标签 multithreading asynchronous webserver multiprocessing

随着我对 Web 服务器软件进行了更多研究,我开始质疑 Apache 基于线程/进程的方法与 Nginx 和 Lighttpd 等服务器提供的异步请求处理相比是否可行,后者倾向于扩展更重的负载更好。

我知道后两者和 Apache 之间还有许多其他差异。我的问题是在什么情况下我会选择基于线程/进程的方法而不是异步处理。

  • 是否有任何我不能与异步方法一起使用的功能/技术(或者功能很差/不太好)?
  • 什么情况会导致异步方法的性能比基于线程/进程的方法性能更差?这些是常见的还是罕见的,区别有多大?
  • 在比较两者时,我还应该考虑其他因素吗?请记住,我主要关注基于线程/进程的方法与异步方法,而不是任何恰好使用这些方法之一的特定服务器软件。这些问题可能是管理/调试困难、安全问题等。
  • 最佳答案

    这是旧的,但值得回答。让我们首先从每个模型的工作原理开始。

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

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

    Are there any features/technologies that I can't use with an asynchronous method (or would function poorly/not as well)?



    是的,当您进行数字运算时。异步(或“事件”)系统的架构非常适合传递数据但不处理数据。它可以处理数千个并发操作,但因为它只运行在一个 OS 线程上,它触发的回调需要尽可能少地执行以获得最大吞吐量。这是因为如果您的一个回调进行了一些需要 5 秒的数字运算,那么您的整个服务器将被卡住 5 秒,直到该操作完成。这个想法是获取数据,将其发送到它要去的地方(数据库、API 等),然后以最少的处理发送响应。

    异步适用于网络 I/O:在多个源/目的地(以及用户界面,但这超出了本文)之间传递数据。

    What situations would cause the performance of an asynchronous method to perform worse than a thread/process based approach? Are these common or rare cases, and how big is the difference?



    见上文,但任何时候你做的 CPU 工作比网络 I/O 多,你应该切换到线程模型。但是,存在一些架构变通方法……例如,您可以拥有一个异步应用程序,并且只要它需要执行实际工作,它就会将作业发送到工作队列。但是,如果每个请求都需要 CPU 处理,那么该架构就有点过分了,您不妨只使用线程服务器。

    Are there any other factors I should take into consideration when comparing the two? Keep in mind I'm focusing mainly on the thread/process based method vs. asynchronous, not any particular server software which happens to utilize one of these methods. These concerns might be difficulty of managing/debugging, security issues, etc.



    异步编程通常比线程编程更复杂。也就是说,如果您不是自己进行编程(即您在 nginx 和 apache 之间进行选择),那么我通常建议您使用异步(nginx),因为您通常可以通过这种方式从服务器中榨取更多的汁液.我总是赞成在堆栈中使用尽可能多的异步。

    也就是说,如果您正在编写应用程序并试图决定是使用线程模型还是异步模型,则必须考虑开发人员的时间。除非你使用的语言在事件循环上有绿色线程(比如方案),否则你会因为流氓异常崩溃你的整个应用程序而把你的头发扯掉很多,并且通常会绕着你的头CPS/对所有事情使用回调。 Futures/promises 是你的 friend ,但只是使异步更好的创可贴。

    TL; 博士

    异步,当在服务器中使用时,如果您正在执行网络 IO 而没有其他任何事情,则可以比线程处理(很多)更多的并发操作。

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

    除非您的语言支持“假”线程(即绿色线程),否则异步编程要困难得多。一旦你过了最初的驼峰,你就没事了,一般来说。如果您没有绿色线程,请使用 promise 。

    如果您可以选择线程和异步作为堆栈中的一个组件(apache 与 nginx),并且它们提供完全相同的功能,那么稍微倾向于异步。不要只是选择它,因为你认为它会让一切都快 20 倍。

    关于multithreading - 为什么我会选择基于线程/基于进程的方法与异步 Web 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12924124/

    相关文章:

    java - 带有发送器的生产者消费者

    java - 让 Bolt 拥有一个后台线程(消费者线程)来独立于传入元组执行操作的效率有多高?

    asynchronous - 如何快速停止 Camel 中的 seda

    regex - 用 Varnish +正则表达式替换页面中的内容

    c - 适当的条件变量用法

    c++ - Windows C++ 线程参数传递

    asynchronous - 异步FromBeginEnd接口(interface)

    wpf - 我应该在UI Thread或Task.Run上使用async等待来处理多个文件吗?

    python - 如何仅使用相对路径加入?

    java - 为 Java HTTP 服务器构建 http header