我正在开发基于服务器 - 客户端通信的系统,我正在尝试确定处理多个客户端的最佳方式。重要的是我不想使用任何第三方库。
在互联网的许多地方,我看到通过为每个连接创建一个单独的线程来解决这个问题,但我不认为这是最好的方式,因为我认为会有大量的连接(也许我错了) )。所以,我正在考虑的解决方案是
创建事件队列并由工作人员处理它们 - 定义的线程池(其中有一个常数n个工作者)。这个解决方案看起来很慢,但我无法想象在处理大量客户端时会有多大差异。
我一直在考虑通过多实例化服务器(在不同的物理机器上)进行负载平衡,但它只是一个很好的附加组件,而不是解决方案本身。
我知道Java并不是真正的异步友好,但也许我缺乏一些知识,并且有很好的解决方案。我会感激任何消化。
其他信息:
为避免讨论(因为SO不适合他们):
答案 0 :(得分:1)
Java 7在我听说过的NIO包下有真正的异步IO。除了难以理解之外,我对它知之甚少。
java中的基本IO是阻塞的。这意味着使用基本IO可能无法使用固定数量的线程来支持许多客户端,因为在阻止来自未发送数据的客户端的调用时,所有线程都会被绑定。
如果您改变第三方库的想法,我建议您使用Grizzly / Netty查看异步IO。
如果你没有改变主意,请亲自调查NIO。
答案 1 :(得分:1)
我建议从每个连接的一个线程的简单架构开始。尺寸足够大的系统上的现代JVM可以支持数千个线程。即使这个简单的方案有效,你也会感到惊喜。但是,如果您需要300k连接,我怀疑每个连接的一个线程是否可行。 (但我以前错了。)你可能不得不摆弄线程堆栈大小和操作系统资源限制。
排队系统将有助于将连接与处理工作的线程分离,但它会增加从每个客户端收到的每条消息的工作量。这也会增加延迟(但我不确定它有多重要)。如果您有300k连接,那么您可能希望从连接中读取一个线程池,并且您还希望拥有多个工作流的队列。如果你有300k客户端每3秒发送一次数据,那就是100k ops / sec,这是要通过单个队列的大量数据。这可能会成为一个瓶颈。
另一种可能值得研究的方法是拥有一个工作线程池,但不是每个工作者从连接读取器线程写入的队列中读取数据,而是让每个工作者直接处理一堆套接字。使用NIO Selector
让每个线程在多个套接字上等待。比方说,有100个线程,每个线程处理3,000个套接字。或者可能有1000个线程,每个处理300个插槽。这取决于处理每个传入消息所需的数据量和工作量。你必须要做实验。这可能比使用异步I / O简单得多。