繁体   English   中英

在创建将同时为200多个客户端发送/接收任务的服务器时,使用select或多线程(或同时使用)更好吗?

[英]Is it better to use select or multi-threading (or both) when creating a server that will simultaneously send/receive tasks for 200+ clients

我正在创建一个服务器,该服务器将同时发送和接收来自200多个客户端的任务(将来可能会有更多的客户端)。 客户端上还将有后台引擎,这些后台引擎将执行任务并将响应发送到服务器而无需先询问。 我希望双向都有大量的信息传递。 我一直在研究多线程并使用select函数,但我想知道给定项目的某些参数,根据流量的多少,哪个选项(或组合)将是最有效的可扩展解决方案。可能会发生。

任何建议将不胜感激。 我很乐意回答任何问题以使内容更加清晰。

两种方法都行得通; 到目前为止,“更好”将在很大程度上取决于您如何定义“更好”一词。

  • 单线程方法避免了竞争状况或死锁问题的任何可能性,因为这些问题固有地不会在单线程程序中发生。 在多线程程序中,您必须非常小心数据锁定模式,否则您将发现自己尝试调试非常神秘的故障,这种故障仅每隔几天/几周/几个月发生一次。

  • 另一方面,单线程方法将您限制为使用单个内核。 它将无法利用现代多核CPU来提高并行处理速度。

  • 第三,如果各种线程/连接经常需要访问任何共享/可变的数据结构,则多线程方法可能会变得冗长(并失去其加速潜力)。 在这种“共享数据瓶颈”的情况下,线程可能会花费大量时间来等待锁定互斥锁,然后无论如何您还是会回到使用单个内核。 如果每个连接独立于其他连接运行(例如,作为简单Web服务器的一部分),并且不需要与其他线程进行交互,则不必担心。

  • 多线程允许您使用阻塞I / O(比非阻塞I / O易于实现),但阻塞I / O限制了您对线程的控制(例如,如何使线程干净退出或占用一些线程)其他非客户端启动的操作,如果该操作在recv()调用中被无限期阻止,则该问题没有任何好的解决方案,只有较差的解决方案)

  • 单线程要求您使用非阻塞I / O(否则,当服务器在send()recv()调用中被阻塞时,单个无响应的客户端可以停止对所有其他客户端的服务)和非阻塞I / O。 O很难正确执行,因为您必须妥善处理部分读取和部分写入。

  • 如果您的程序曾经需要执行大量的计算或文件I / O,请注意,单线程设计将强制所有客户端等待任何客户端的计算(或I / O)完成。 在多线程设计OTOH中,当客户端A忙于从磁盘读取数据或处理数字时,客户端B到Z可以继续在其他内核/线程上进行服务。

  • 生成和维护线程的开销将因一个OS而异。 如果要同时运行数百个线程,则可能需要首先验证目标操作系统(和硬件)将能够有效处理该负载。 (您可以减少通过线程池产生和收获线程的开销,但要以增加RAM使用量为代价)

我个人更喜欢单线程/非阻塞I / O方法,因为如果您希望程序能够干净,可靠地关闭(如果应该这样做,则应该这样做),阻塞I / O是有问题的。例如,在valgrind下进行内存泄漏测试)。 如果单核性能不足,通常可以很简单地将“ N个套接字处理”线程设计扩展到更强大的“ M个线程处理”线程设计,然后您可以尝试使用不同的N和M值,直到找到可以提供最佳性能的值为止(例如,通过将M设置为主机上的内核数,并将新接受的套接字分发给任何线程)当前处理的套接字数量最少)

我曾经用Java创建一个程序,一个聊天应用程序,它与建立的服务器的每个连接都代表服务器中的一个新线程,用于管理相关客户端。

在Server类内部,有一个静态变量来管理连接了哪些客户端。

我不知道推荐不同的技术是否是回答您问题的正确方法,但是我认为,对于您的情况,看看Erlang / Elixir平台是一个好主意,前提是能够保持同时有很多客户

当前,像Whatsapp这样的大公司都在使用Erlang和Discord Elixir。

希望我的回答对您有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM