【问题标题】:Server multi-threading, a must for Protocol ? and more服务器多线程,Protocol 必备?和更多
【发布时间】:2010-01-29 16:50:39
【问题描述】:

假设应用层协议是通过 UDP 实现的。需要客户端超时,因此服务器需要保持与之对话的每个客户端的状态。

还假设使用了select

  1. 实现多线程服务器总是最好的吗?我认为链接列表也会这样做,其中服务器超时 time=Earliest Timeout of a client- CurrentTime 。链接列表将具有与保持客户端状态相同的功能,同时避免创建新线程的开销(尽管为服务器维护特定于客户端的超时引入了一些复杂性)。

  2. 如果选择多线程,那么为新客户端调用新套接字是否最好?这将引入系统资源开销。但我认为默认服务器套接字(bind 具有服务器知名端口)会做同样的事情,因为它有缓冲区(嗯..对于可扩展的客户端数量来说可能不够长..)

谢谢!

【问题讨论】:

    标签: c architecture networking protocol-buffers


    【解决方案1】:

    根据我的经验,当可怕的同步问题潜伏时,线程可以很容易地让您的代码看起来合乎逻辑和干净,等待某些事件以正确的顺序发生,导致应用程序崩溃。线程是一个非常有用的工具——如果你的应用程序能够充分利用你的 CPU,你需要考虑线程,学习使用线程是学习利用分布式处理的一步(至少,我想是的)。

    我的偏好是使用异步回调而不是阻塞调用来编写应用程序,并明确指示我想使用哪个线程来处理回调。这具有以下优点:

    • 它使状态变量交互更加可控,因此可预测,这意味着线程更加健壮。
    • 如果操作正确,它可以充分利用 CPU 的处理器数量。
    • 它允许你直接控制你想给某些函数的优先级——如果这个函数是高优先级的,你把它分派给一个高优先级的线程,然后当它完成时,它把结果发送回低优先级的线程通过调用者线程中的延续来优先调用者。或到另一个线程 - 没有理由限制这一点。
    • 通常可以移植到非线程环境。也许对大多数人来说并不重要,但有时对我来说很重要。

    【讨论】:

    • 感谢您的建议。我想我会改用常规模型。但是与双核相比,线程在单核系统上并没有那么有用。
    • @Computer Guru - 相对于轮询架构而言确实如此,但我认为相对于精心设计的基于 AIO(或其他基于中断)的架构而言,情况并非如此。在单核上,线程基本上减少为基于中断的架构。
    【解决方案2】:

    我不会提出任何 Aidan Cully 没有回答的新内容,但是,请看一下 Apache 的多处理模块背后的理论:http://www.linuxquestions.org/linux/answers/Networking/Multi_Processing_Module_in_Apache

    本质上,服务器分为多个模块,并创建线程/进程来管理连接,具体取决于需要和配置选项 - 这听起来像 Aidan 的回答中描述的平衡,尽管 Apache 实现可能略有不同。

    【讨论】:

    • 是的,Apache (httpd) 社区在引入其处理模型时,我还是比较活跃的,围绕它的讨论与我的想法有很大关系。
    【解决方案3】:

    链接列表不会扩展。

    在服务器端使用链表逐一检查客户端并满足他们的需求对于 5 到 10 个客户端来说都很好。但是当你有 100 个时会发生什么? 1000?如果一个客户的请求需要很长时间来处理会发生什么?

    线程不只是为单个客户端提供维护状态的方法。它们还提供了一种在所有客户端上同时“分配服务器资源”的方法。就好像每个客户端都有自己的专用服务器,(几乎)没有队列:客户端想要一些东西,它询问服务器,服务器回复。它是瞬时的。

    另外,使用链表方法可能会浪费宝贵的资源。如果所有客户除了一个客户什么都不想要怎么办?您将反复循环超过一百个客户端,除了浪费 CPU 周期之外什么都不做,直到遇到确实需要服务器注意的客户端。

    【讨论】:

    • 这是一个相当笼统的声明。我已经看到 EFNet 服务器愉快地处理超过 15,000 个并发客户端 - 使用单线程 ircd,基本上是所描述的方法。所以它很有可能是可扩展的足够
    【解决方案4】:

    多线程绝对不是必须的,因为您已经想出了一个替代方案。我们不能真正使用像 alwaysnever 这样的绝对值,因为每种情况都有独特的要求和约束。

    是的,为每个连接添加一个新线程/套接字会消耗更多资源。听起来您需要很好地定义您需要多少连接。然后你可以确定你是否有足够的资源。

    如果资源限制不是问题,我会选择更简单的解决方案。与编写新的功能体(链表建议)相比,使用您已经拥有的工具(即处理线程和套接字的经过良好测试的函数)更容易吗?代码维护呢?如果将来有其他程序员从事这个项目,他们是否更容易理解使用他们已经熟悉的标准操作系统调用或链表的实现?

    【讨论】:

    • 感谢您的解释,尤其是维护部分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-24
    • 2015-08-11
    • 2019-01-20
    • 2019-05-27
    • 2015-02-10
    相关资源
    最近更新 更多