我将创建一个网络系统,可以处理7000+ tcp套接字客户端,输入 5KB / s (客户端发送)。我调查过这个问题:Link>>。他们说“创建1024个线程来处理1024个客户端”。我知道有一个名为 “select()” 的方法,我认为我无法打开7000多个线程来处理7000多个客户端,因为我的处理器(或服务器)有只有8CPU,这意味着7000多个线程是一个很大的错误。现在我想我将创建~1000个线程,我将处理这个线程中的每个7个套接字组。但现在问题是:如果我有相同的应用程序,但我有2CPU处理器,我无法获得1000个线程的最大性能,我应该创建(可能)500个线程。否则,如果我有8CPU处理器,我无法获得最大值。具有1000个线程的性能,我需要创建(可能)2000个线程来处理套接字。我怎么能理解“这个处理器可以处理X线程”?这是真的吗?
编辑:我想我可以创建一个正在观看节目的专家。也就是说,每个线程记录“我已经在X秒内完成了我的工作”。和profiller处理此消息并决定创建一个线程或杀死一个线程。但是如何理解线程的(或CPU)状态?
答案 0 :(得分:12)
单个服务器无法处理35 Gb /秒的流量(即使有,也会非常昂贵)。
我解决这个问题的方法是:
您希望从第一行代码中集中注意力的事情:
修改强>
所以它在 KB 中,这要好得多:)。我仍然建议先考虑LB。
有不同的技术和协议可以帮助您编写有效的应用程序。根据个人经验,我更喜欢HTTP到TCP。有许多好的负载平衡器可用,添加压缩,加密,身份验证只需几天。
如果您执行任何IO操作来处理客户端请求,我也听说node.js是超高速的。
我编写的服务器是ASP.NET Web API应用程序,每个应用程序处理几MB /秒。将服务器隐藏在负载均衡器后面是微不足道的(我使用HAProxy和nginx但是肯定还有很多其他可用。我也使用C ++套接字服务器,它的开发时间要长得多。我的观点是的,如果你可以使用高级语言,则更喜欢低级语言。这会缩短你的开发时间(在我的情况下缩短10倍!)并使生活更轻松。
答案 1 :(得分:0)
第一个问题是服务器做了什么?在每个客户端请求期间它会被cpu绑定还是IO绑定?
如果它是CPU绑定的,那么尝试并行处理它们几乎没有意义,因为你没有比服务器上的核心数更多的并发性。在这种情况下,您也可以创建与服务器上的核心一样多的线程,并尽可能快地串行处理输入。
如果服务器进程是IO绑定的,那么您需要确定处理客户端请求的每个线程将空闲多长时间,这将使您了解创建有多少线程。这是经典的方法,但正如其他人所指出的那样,在这种情况下,更现代的方法是使用异步编程库。对于Windows上的C ++,将是PPL。
更新
你似乎非常渴望保持低水平,所以要正确处理原始问题的核心,即如何计算核心支持的线程数。
首先,您要为线程调用的任何阻塞调用创建包装函数(记录每个线程被阻塞的时间)。从这些指标中,您可以确定平均线程占用率,并且一旦您知道获得最佳线程数的粗略计算就足够了。
thread_occupancy = (thread_run_time - thread_blocked_time) / thread_run_time
optimal_thread_count = num_cores / thread_occupancy
您可能希望将至少0.1(10%)添加到thread_occupancy以涵盖线程切换开销。
但是,正如其他人所说,这种经典的多线程方法仅适用于几十个线程。一旦操作系统必须控制一百个线程的调度,那么调度开销就会增加,以至于添加更多线程不会带来任何好处。虽然这种情况发生在很大程度上依赖于系统和软件,所以你只需要进行一些测试即可获得最佳点。
如果您的操作受IO限制,您希望同时处理数百或数千个请求,那么您别无选择,只能使用异步处理来处理每个线程的多个请求,这通常要求使用异步库。在这种情况下,每个核心通常会有一个线程在异步库的控制下完全占用。这可能由库本身处理,或者您可能需要手动设置它,但无论哪种方式都不需要运行时控制线程数,因此您可以监视线程占用率,就像纯多线程方法一样你不会对这些信息做太多的事情。