每个连接的线程与Reactor模式(带有线程池)?

omn*_*nse 13 c++ poco-libraries

我想写一个简单的多人游戏作为我的C++学习项目的一部分.

所以我想,既然我在这里,我想做得恰到好处,而不是仅仅完成它.

如果我理解正确:Apache使用每个连接的线程架构,而nginx使用事件循环,然后为传入连接专用一个worker [x].我想nginx更明智,因为它支持更高的并发级别.对?

我也遇到过这个聪明的比喻,但我不确定它是否适用于我的情况.这个比喻似乎也很理想主义.我很少看到我的电脑以100%的CPU运行(即使打开了一个不常见的Chrome标签,Photoshop也没有同时运行)

此外,我遇到了一个SO帖子(不知何故,它从我的历史中消失了)用户询问他们应该使用多少线程,其中一个答案是拥有大约700个,甚至多达10,000个线程是完全可以接受的.不过,这个问题与JVM有关.

所以,让我们估计一个虚拟的用户群,大约有5000个用户.哪种方法应该是"最并发"的方法?

  1. 在一个线程中运行所有内容的reactor模式.
  2. 带有线程池的反应器模式(大概,你建议线程池应该有多大?
  3. 每个连接创建一个线程,然后销毁连接关闭的线程.

我承认选项2听起来对我来说是最好的解决方案,但我在所有这些方面都非常环保,所以我可能有点天真并且缺少一些明显的缺陷.而且,听起来它可能相当难以实现.

PS:我正在考虑使用POCO C++库.建议任何替代库(如boost)都可以.然而,许多人说POCO的图书馆非常干净且易于理解.所以,我最好使用一个,这样我就可以了解如何我使用的是什么样的秒.

iai*_*ain 12

当正确编写时,反应式应用程序肯定会更好地扩展.这意味着

  • 永远不要阻止反应线程:
    • 任何阻塞都会严重降低服务器的性能,通常使用少量的反应式线程,因此阻塞也会很快导致死锁.
    • 没有互斥锁,因为这些可以阻塞,所以没有共享的可变状态.如果您需要共享状态,则必须使用actor或类似程序将其包装,以便只有一个线程可以访问该状态.
  • 响应线程中的所有工作都应该是cpu绑定的
    • 所有IO必须是异步的,或者在不同的线程池中执行,结果反馈到反应器中.
    • 这意味着使用期货或回调来处理回复,如果您不习惯并且遵守纪律,这种代码风格很快就会变得无法维护.
  • 反应线程中的所有工作都应该很小
    • 为了保持服务器的响应能力,反应堆中的所有任务必须很小(受时间限制)
    • 在8核机器上,您不能同时允许8个长任务到达,因为在完成之前不会启动任何其他工作
    • 如果任务可能需要很长时间,则必须将其分解(合作多任务处理)

响应式应用程序中的任务由应用程序而非操作系统调度,这就是为什么它们可以更快并且使用更少的内存.当您编写Reactive应用程序时,您说您很了解问题域,以至于您可以更好地组织和安排此类工作,而不是操作系统可以调度线程以阻塞方式执行相同的工作.

我是反应式架构的忠实粉丝,但他们带来了成本.我不确定我会把我的第一个c ++应用程序写成反应,我通常会尝试一次学习一件事.

如果您决定使用反应式架构,请使用一个可以帮助您设计和构建代码的良好框架,否则最终会出现意大利面.要寻找的是:

  • 什么是工作单位?
  • 添加新作品有多容易?它只能来自外部事件(例如网络请求)
  • 将工作分解成更小的块是多么容易?
  • 处理这项工作的结果有多容易?
  • 将阻塞代码移动到另一个线程池并仍处理结果有多容易?

我不能为此推荐一个C++库,我现在在ScalaAkka中进行我的服务器开发,它提供了一个优秀的可组合期货库来保持代码清洁.

祝你好运学习C++,并选择你做出的选择.

  • @Zombies如果你想迂腐,问题是哪一个是最并发的1)单线程反应器2)带有线程池的反应器3)每个连接的线程。这个问题的答案很大程度上取决于你的工作负载,是否存在阻塞 IO?请求是否必须协调对状态的访问?国家在变异吗?我明确表示,如果书写正确,反应性尺度会更好。所以答案是 1 或 2。然后向提问者提供足够的信息,让他们根据自己的工作量决定是选择选项 1 还是选项 2。同样重要的是,我帮助他们决定是否可以正确实施。 (2认同)

Jam*_*ock 7

选项2将最有效地占用您的硬件.这是经典文章,十年之久但仍然很好.

http://www.kegel.com/c10k.html

目前用于构建具有并发和异步等待的应用程序的最佳库组合是Boost Thread和Boost ASIO.您也可以尝试使用C++ 11 std threadstd mutex(但是在很多情况下,Boost ASIO比互斥锁更好,只是总是回调到同一个线程,而您不需要受保护的区域).远离std future,因为它破碎了:

http://bartoszmilewski.com/2009/03/03/broken-promises-c0x-futures/

线程池中的最佳线程数是每个CPU核心一个线程.8个核心 - > 8个线程.如果您认为您的线程池线程有时可能会调用阻塞操作,那么可能还需要额外的一些.

  • `std future`被_not_打破!! C++ 11缺少一个可以轻松编写它们的功能.换句话说,`std future`就好了,但是在某些情况下,彻底和有效地使用它们并不是那么容易.也就是说,+ 1不管:P (6认同)