这是旧的,但值得回答。让我们首先说每个模型是如何工作的。
在线程中,您有一个请求进入处理程序,处理程序产生一个新的操作系统线程来处理该请求,并且该请求的所有工作都发生在该线程中,直到发送响应并结束线程。此模型支持与服务器可以生成的线程一样多的并发请求(但线程可能有些重量级)。
当执行异步请求时,请求进入处理程序,但不是创建线程来处理它,而是将连接添加到所谓的事件循环中。事件循环监听连接上的数据/状态变化,并在每次“某事”发生时触发回调。将连接添加到事件循环后,处理程序立即侦听要添加的新连接。这允许您同时拥有许多(有时是 100K)并发连接。
是否有任何我不能与异步方法一起使用的功能/技术(或功能不佳/效果不佳)?
是的,当您进行数字运算时。异步(或“事件”)系统的架构使得它擅长传递数据但不处理数据。它可以处理数以千计的并发操作,但是因为它只在一个 OS 线程上运行,所以它触发的回调需要做的尽可能少,以获得最大的吞吐量。这是因为如果您的某个回调执行一些需要 5 秒的数字运算,那么您的整个服务器将冻结 5 秒,直到该操作完成。这个想法是获取数据,将其发送到它要去的地方(数据库、API 等)并以最少的处理发送响应。
异步有利于网络 I/O:在多个源/目标之间传递数据(以及用户界面,但这超出了本文的范围)。
哪些情况会导致异步方法的性能比基于线程/进程的方法更差?这些是常见的还是罕见的情况,差异有多大?
见上文,但任何时候你做的 CPU 工作比网络 I/O 多,你应该切换到线程模型。但是,有一些架构变通方法......例如,您可以拥有一个异步应用程序,并且只要它需要进行实际工作,它就会将工作发送到工作队列。但是,如果每个请求都需要 CPU 处理,那么这种架构就太过分了,您不妨只使用线程服务器。
在比较两者时,我还应该考虑其他因素吗?请记住,我主要关注基于线程/进程的方法与异步,而不是碰巧使用这些方法之一的任何特定服务器软件。这些问题可能是管理/调试困难、安全问题等。
异步编程通常比线程更复杂。也就是说,如果您不是自己进行编程(即您在 nginx 和 apache 之间进行选择),那么我通常建议您使用异步(nginx),因为您通常可以通过这种方式从服务器中榨取更多汁液. 我总是赞成在堆栈中使用尽可能多的异步。
也就是说,如果您正在编写应用程序并尝试决定是使用线程模型还是异步模型,则必须考虑开发人员的时间。除非您使用的语言在事件循环(如方案)上具有绿色线程,否则预计会因流氓异常导致整个应用程序崩溃并且通常将您的头绕在CPS周围/使用回调处理所有事情。Futures/promises 是你的朋友,但只是使异步更好的创可贴。
TL;博士
异步,当在服务器中使用时,如果你正在做网络 IO 而不做其他事情,它可以比线程压缩(很多)更多的并发操作。
如果您正在处理任何类型的数字运算,请使用线程应用程序服务器或使用带有后台排队系统的异步应用程序。
异步编程要困难得多,除非您的语言支持“假”线程(即绿色线程)。一旦你克服了最初的驼峰,你就没事了,一般来说。如果您没有绿色线程,请使用承诺。
如果您可以选择线程和异步作为堆栈中的组件(apache 与 nginx),并且它们提供完全相同的功能,则稍微支持异步。不要仅仅因为你认为它会让一切都快 20 倍而选择它。