.net 处理服务中传入请求的体系结构

.net 处理服务中传入请求的体系结构,.net,networking,architecture,scalability,parallel-processing,.net,Networking,Architecture,Scalability,Parallel Processing,我正在为一个项目设计一个服务器守护进程,该项目必须同时接收大量请求并异步处理它们。我知道这样一个项目的绝对规模,但我对它很认真,并试图在继续之前做出明确的设计和计划 以下是我的目标清单: 可扩展性-必须能够将架构并行化到多个处理器甚至多个服务器上 能够处理大量并行连接 如果处理单个请求需要很长时间,则不能导致阻塞问题 请求-响应周转时间必须最短 围绕.NET框架构建(将用C#编写) 我提议的体系结构和流程相当复杂,因此下面是我最初设计的图表: (如果它的大小调整不好) 其思想是请求通过网络

我正在为一个项目设计一个服务器守护进程,该项目必须同时接收大量请求并异步处理它们。我知道这样一个项目的绝对规模,但我对它很认真,并试图在继续之前做出明确的设计和计划

以下是我的目标清单:

  • 可扩展性-必须能够将架构并行化到多个处理器甚至多个服务器上
  • 能够处理大量并行连接
  • 如果处理单个请求需要很长时间,则不能导致阻塞问题
  • 请求-响应周转时间必须最短
  • 围绕.NET框架构建(将用C#编写)
我提议的体系结构和流程相当复杂,因此下面是我最初设计的图表:

(如果它的大小调整不好)

其思想是请求通过网络进入(尽管我还没有决定TCP或UDP是最好的),并立即传递到高速负载平衡器。然后,负载平衡器使用加权随机数生成器选择一个请求队列(RQ)来放置请求。权重来自每个队列的大小。使用加权RNG而不仅仅是将请求放入最不繁忙的队列的原因是,它可以防止空但被阻塞的队列(由于挂起的请求)锁定整个服务器。如果所有RQ超过一定大小,负载平衡器将丢弃请求并将“服务器太忙”响应放入输出队列(OPQ)-此部分未在图中显示

每个队列对应一个线程,其关联性设置为服务器上的一个CPU核心。这些线程是并行请求处理器的一部分,并行请求处理器使用来自每个队列的请求。请求分为三种类型之一:

  • 立即-立即请求,顾名思义,是立即处理的

  • 可延迟的-可延迟的请求被视为低优先级。它们在低负载期间立即被处理,或者在负载较高时被放入延迟请求队列(DRQ)。负载平衡器从DRQ获取这些延迟请求,将它们标记为立即请求,然后将它们放回相应的RQ中

  • 定时-定时请求与目标时间戳一起放入定时请求队列(TRQ)。这些请求通常由另一个请求生成,而不是由客户端显式发送。当超过请求时间戳时,下一个可用的请求处理器线程将使用它并对其进行处理

  • 处理请求时,可以从内存中的键/值对缓存、磁盘上的键/值对缓存或专用SQL数据库服务器获取数据。缓存的值将是BSON,索引将是字符串。我正在考虑使用
    字典
    在内存中实现这一点,并为磁盘缓存使用btree(或类似工具)

    处理完成时创建响应,并将其放入输出队列(OPQ)。然后,循环使用来自OPQ的响应,并通过网络将它们传输回客户端。如果OPQ达到其最大大小的80%,则四分之一的请求处理器线程将暂停。如果OPQ达到其最大大小的90%,一半的请求处理器线程将暂停。如果OPQ达到其最大大小,则所有请求处理器线程都将暂停。这将通过一个信号量来实现,该信号量还应防止单个请求处理器线程被阻塞并留下过时的请求

    我想要的是关于以下几个方面的建议:

    • 这个架构是否有我遗漏的重大缺陷
    • 有什么值得考虑的原因吗?
    • TCP或UDP是否更适合于请求?拥有TCP提供的“交付证明”是非常有用的,但是UDP的轻量级特性也很吸引人
    • 在Windows服务器上处理超过100k的同时连接时,我需要考虑哪些特殊的考虑事项?我知道Linux的TCP协议栈处理得很好,但我对Windows不是很确定
    • 我还有其他问题要问吗?我忘了考虑什么了吗?
    我知道这本书有很多要读,也可能有很多要问的,所以谢谢你抽出时间


    图表的更新版本。

    如果您希望此图表能够很好地扩展,您需要确保所有组件都是可扩展的-处理元素、输入/输出块和队列。如果您打算在Microsoft堆栈上执行此操作,我会认真建议您研究Windows Azure,它提供您所需的大部分(如果不是全部)关键功能。有一件事您没有提到——是否会有一个持久存储层(例如数据库)?如果是这样,也要做好扩展的准备,否则它将成为您的单点故障。

    我不明白您为什么需要多个请求队列。在我看来,您只需要一个请求队列,许多处理器都从中读取数据。任何排队系统都不会有问题。只有一个队列将输入与处理器分离,允许更好的可伸缩性——在需要时启动更多处理器,没有其他人需要关心它

    至于TCP和UDP,你想要什么样的性能?使用一些现有的通信基础设施(如ZeroMQ)为您解决这些技术问题不是更好吗


    <>:

    也可以考虑如下:

    • 故障转移。您可以设计一种在可能的服务崩溃时持久化请求的方法,这样即使在服务重新启动后,所有挂起的请求都将得到处理
    • 错误队列。(也称为patte