为啥在处理客户端请求时异步模式优于同步模式?

Posted

技术标签:

【中文标题】为啥在处理客户端请求时异步模式优于同步模式?【英文标题】:Why is the Asynchronous mode is better than the Synchronous one when handling clients requests?为什么在处理客户端请求时异步模式优于同步模式? 【发布时间】:2010-07-01 21:44:14 【问题描述】:

我有一个客户端-服务器项目,正在寻找更好的方式来处理来自客户端的请求。有人建议异步模式优于同步模式和线程池模式。 我的问题是为什么?异步模式有什么缺点吗?

【问题讨论】:

【参考方案1】:

是的,通常可以在不消耗线程的情况下处理异步请求。操作系统对它们有特殊的支持,如重叠 I/O 和完成端口等功能。他们本质上所做的是利用内核线程的开销,无论如何都需要内核线程,因为驱动程序需要能够处理来自多个用户模式程序的多个请求。 .NET 框架很容易在其 BeginXxx() 方法中利用这一点。

使用线程池线程也很便宜,但您会受到线程池调度程序的影响。这不太喜欢启动更多的 TP 线程然后有内核。 TP 线程永远不应该用于可能会被阻塞一段时间的代码,这对于建立连接之类的 CS 任务来说非常典型。

异步代码中的错误处理非常困难。当 EndXxxx() 方法引发异常时,您通常只有很少的上下文。它发生在一个回调线程上,离主逻辑很远。好吧,当您可以耸耸肩“没有发生,让我们记录它”时,当程序的状态取决于它时,完全混乱和重振。在后一种情况下始终选择同步模式。

【讨论】:

+1 他们甚至比这更好:通常不需要内核线程(大多数驱动程序甚至没有线程)。【参考方案2】:

您不想阻止用户界面。通过异步操作,您可以在等待服务器响应的同时做其他事情。

【讨论】:

【参考方案3】:

异步模式让您继续处理,而同步模式让您等待。

【讨论】:

简单而简短的答案,但足够解释。谢谢@Brian【参考方案4】:

同步操作的一个缺点是 IMO 不能中断它们 - 例如当您的服务器应用程序调用同步方法 WaitForConnection() 并且没有客户端连接时,您无法停止等待...

例如试试看这个What is a good way to shutdown Threads blocked on NamedPipeServer#WaitForConnection?

【讨论】:

【参考方案5】:

按照 Hans 的回答“标记”:I/O 操作与线程的独立性允许更显着的扩展;数以万计的未完成请求是可能的,这根本无法使用线程来完成。

另外,当你启动considering the complexities of error handling in protocol design 时,发现异步方法的复杂度远低于正确编写同步代码的复杂度。大多数同步套接字代码看起来更简单,但实际上包含一些细微的错误。

如果双方发送的数据多于读取的数据,异步方法对于防止死锁情况也很重要;更多讨论请参见this blog post。

如果您希望线程安全包装器中异步 I/O 的可靠性优势和(大部分)性能优势(具有更简单的错误处理),请考虑使用 Nito.Async 库。

【讨论】:

【参考方案6】:

在同步服务器中,您必须在访问数据结构时处理锁​​(如果存在更新),这需要时间和代码(并且是难以找到错误的来源)。同样拥有许多(例如数千个)线程会在许多实现(例如堆栈分配)中带来技术问题,如果服务器受 IO 限制,那么这些线程几乎都处于休眠状态(等待网络)并且只是浪费内存。

在单线程上使用异步模型,您可以忽略锁定问题(这意味着您的处理速度尽可能快)并且您只使用客户端实际需要的内存(只有一个堆栈)。

然而,现在多核机器相当普遍,因此失去了部分优势(因为如果修改共享数据结构,您必须锁定)。在 N 个异步服务器前使用平衡器可能会获得最佳效率,其中 N 是您的环境的最佳线程数。

异步方法的不好的一面是,根据您的工具,代码可能非常丑陋且难以理解,并且如果计算不是微不足道的并且您的处理错误地进入了无限循环,则整个异步服务器将无响应(所以可能应该添加一个看门狗)。

【讨论】:

异步并没有解决锁定问题。您可以通过不同线程上的多个回调重新输入异步回调。使用异步模型时,您仍然需要保护任何共享状态。 使用抢占式多线程编码正确锁定的问题是切换是“不可见的”并且可以随时发生。异步实现中的切换点是固定的并且通常是绝对明显的。由于确定性,调试也简单得多。虽然仍然可能存在某种形式的“逻辑”锁定,但在我看来,这与在共享数据更新方法中获得正确锁定的难度相比没有任何意义。 @heavyd:在我看来,重新阅读您的评论似乎存在术语问题。我说过,通过单线程异步实现,您可以忘记锁定问题......(意思是关于并发访问的物理锁定,而不是自动机状态更改之间的逻辑锁定,这当然是强制性的)以及如果异步不加上单线程那么这个优势就丧失了。在您的评论中,您谈到了不同的主题,因此可能对这些术语有一些误解。

以上是关于为啥在处理客户端请求时异步模式优于同步模式?的主要内容,如果未能解决你的问题,请参考以下文章

半同步/半异步并发模式进程池实现

小记tomcat三种运行模式

同步与异步的概念

ajax 同步和异步的区别

同步与异步 & 阻塞与非阻塞

同步与异步 & 阻塞与非阻塞