在高性能套接字上使用Async-Await vs ThreadPool与MultiThreading(C10k解决方案?)

我真的很困惑async-await s, pool s和thread s。 主要问题始于这个问题:“当我必须处理10k插槽I / O时,我该怎么办?” (又名C10k问题 )。

  • 首先,我尝试使用一个使用一个主Queue和多个Thread来处理所有传入数据的线程来创建一个自定义池架构。 这是了解thread-safetymulti-threading thread-safety一个很好的经验,但是thread对于现在的async-await是一种过度杀伤力
  • 后来,我使用async-await实现了一个简单的架构,但我无法理解为什么“async和await关键字不会导致创建额外的线程。” ( 来自MSDN )? 我认为必须有一些thread来做像BackgroundWorker这样的工作。
  • 最后,我使用ThreadPool实现了另一个架构,它看起来像我的第一个自定义池。

现在,我认为我应该有其他人对处理C10k感到困惑。 我的项目是我的游戏项目的专用(中央)服务器,它是集线器/大厅服务器,如MCSG的大厅或COD的配对服务器。 我将进行登录操作,游戏服务器命令执行/查询和服务信息(如版本,补丁)。

最后一部分可能对我的项目更具体,但我真的需要一些关于多个(重)数据处理的现实解决方案的好建议。

(也就是说,1k-10k-100k连接处理取决于服务器硬件,但这是一般性问题)


关键点: 在任务并行库和ThreadPool之间选择 (MSDN博客)


[附加]想要了解我们在谈论什么的好(基本)事物:

  1. 主题
  2. 异步,等待
  3. 线程池
  4. 的BackgroundWorker

async / await大致类似于“为每个线程提供服务的许多客户端,并在您引用的文章中使用异步I / O和完成通知”方法。

虽然asyncawait本身不会导致任何其他线程,但如果async方法在线程池上下文中恢复,它们将使用线程池线程。 请注意,与ThreadPoolasync交互是高度优化的; 您是否可以使用ThreadThreadPool获得相同的性能(具有合理的开发时间)是非常值得怀疑的。

如果可以的话,我建议使用现有协议 – 例如SignalR。 这将大大简化您的代码,因为编写自己的TCP / IP协议有很多( 很多 )陷阱。 SignalR可以自托管或托管在ASP.NET上。

不。如果我们使用4.5中引入的.NET的异步编程模式,在大多数情况下我们不需要由我们创建手动线程。 编译器完成了开发人员过去所做的艰巨工作。 创建新线程代价高昂,需要时间。 除非我们需要控制线程,否则“基于任务的异步模式(TAP)”和“任务并行库(TPL)”对于异步和并行编程来说已经足够了。 TAP和TPL使用Task。 通常,Task使用ThreadPool中的线程(线程池是已经由.NET框架创建和维护的线程集合。如果我们使用Task,大多数情况下我们不需要直接使用线程池。一个线程可以做更多有用的东西。你可以阅读更多关于线程池的信息

通过使用异步编程,您可以避免性能瓶颈并提高应用程序的整体响应能力。 异步对于可能阻塞的活动至关重要,例如当您的应用程序访问Web时。 访问Web资源有时会很慢或延迟。 如果在同步过程中阻止此类活动,则整个应用程序必须等待。 在异步过程中,在潜在阻塞任务完成之前,应用程序可以继续执行不依赖于Web资源的其他工作。

Await专门用于处理花费时间的事情,最常见的是I / O请求。 传统上,当I / O请求完成时,回调就完成了。 编写依赖于这些回调的代码非常困难,等待大大简化它。 等待处理延迟,它不执行任何线程所做的事情。 await表达式,即await关键字右侧的内容,是完成工作的原因。 您可以对任何返回Task的方法使用Async。 XxxxAsync()方法只是.NET框架中预先生成的方法,用于需要时间的常见操作。 就像从Web服务器下载数据一样。

我建议你阅读Async和Await的异步编程