我们必须使我们的系统具有高度的可扩展性,并且已经为使用VC ++的Windows平台开发了。 说起初,我们想同时处理100个请求(来自msmq)。 什么是最好的方法? 单线程100线程或2线程50-50线程? 在第二种方法的情况下,除了进程内存之外,还有什么收益呢? 在Windows中首先将CPU时间分配给进程,然后在该进程的线程之间进行拆分,或者OS对每个进程的线程数进行计数,并基于线程而不是进程分配CPU。 我们注意到,在第一种情况下,CPU利用率是15-25%,我们想要消耗更多的CPU。 请记住,我们希望获得最佳性能,因此100个请求就是例子。 我们也注意到,如果我们增加120以上进程的线程数,由于上下文切换性能下降。
还有一点, 我们的产品已经支持集群,但是我们希望在单个节点上使用更多的CPU。
任何build议将不胜感激。
Windows上的标准方法是多线程。 不是说这总是你最好的解决方案,但每个线程或过程都有一个价格,而在一个窗口上,一个过程是更昂贵的。 至于调度程序,我不确定,但你可以设置进程和线程的优先级。 线程的真正好处是它们共享的地址空间和没有IPC的通信能力,但同步必须小心维护。
如果你的系统已经被开发出来,那看起来似乎更容易实现一个多进程的解决方案,特别是如果有一个机会可能会使用多于一台的机器。 由于一台机器上的2个进程的IPC可以在一般情况下扩展到多台机器。 大部分的并行化尝试都失败了,因为整个系统没有对瓶颈进行评估。 例如如果你实现了100个线程,全部写入同一个数据库,那么在实际性能上可能会获得很少的收益,只需等待数据库即可。
只是我的.02
你不能处理更多的请求比你有CPU核心。 “快速”可伸缩解决方案涉及设置线程池,其中活动(不是在IO上阻塞)线程的数量== CPU核心的数量。 所以创建100个线程,因为你想服务100 msmq请求是不好的设计。
Windows有一个称为IO完成端口的线程池机制。
使用IO完成端口确实将设计推向单一进程,因为在多进程设计中,每个进程都有自己独立管理的IO完成端口线程池,因此可以获得更多的线程争夺CPU内核。
IO完成端口的“核心”思想是它的内核模式队列 – 您可以手动将事件发布到队列中,或者通过将文件(文件,套接字,管道)句柄与端口关联来自动获取异步IO完成。
另一方面,IO完成端口机制会自动将事件等待到等待的工作线程上,但是如果它检测到线程池中当前的“活动”线程数超过了CPU核心数,它就不会退出工作。
使用IO完成端口可以潜在地增加服务的可扩展性,但是通常情况下,增益比预期的要小得多,因为当所有的CPU核心争用服务其他资源时,其他因素会迅速起作用。
如果你的服务是用c ++开发的,你可能会发现对堆的序列化访问是一个很大的性能减去 – 虽然Windows 6.1似乎实现了一个低争用堆,所以这可能不是一个问题。
总结 – 从理论上讲,您最大的性能收益将来自使用单个进程管理的线程池的设计。 但是,你严重依赖于你正在使用的库,不能序列化访问关键资源,这可能会很快失去理论上的性能收益。 如果你有库代码序列化你很好的线程化服务(如c ++对象的创建和销毁由于堆争用而被序列化的情况),那么你需要将库/交换器的使用改为低争用版本的库或者只是扩展进入多个进程。
唯一的方法是编写测试用例,以各种方式强调服务器并测量结果。