Java 这种网络设计是非阻塞NIO性能改进的候选方案吗?

Java 这种网络设计是非阻塞NIO性能改进的候选方案吗?,java,multithreading,io,connection-pooling,nio,Java,Multithreading,Io,Connection Pooling,Nio,我有一个通用的回合制游戏,我正在开发,目前它是如何运作的: 使用boneCP(连接池)、MySQL数据库、java服务器、android客户端,很快就会有一个线程池 客户端向服务器发出请求。 Java服务器生成一个新线程来处理请求。 服务器发送响应。 TCP套接字终止 每个客户端不需要保持持久(持久)连接的负载,而是每隔(x)个间隔戳一次服务器,询问是否轮到他们了。如果没有,它什么也不做。如果是,它可以输入并将其移动发送到服务器 有了这种类型的服务器驱动网络,我是否可以在将所有内容转换为NIO方

我有一个通用的回合制游戏,我正在开发,目前它是如何运作的: 使用boneCP(连接池)、MySQL数据库、java服务器、android客户端,很快就会有一个线程池

客户端向服务器发出请求。 Java服务器生成一个新线程来处理请求。 服务器发送响应。 TCP套接字终止

每个客户端不需要保持持久(持久)连接的负载,而是每隔(x)个间隔戳一次服务器,询问是否轮到他们了。如果没有,它什么也不做。如果是,它可以输入并将其移动发送到服务器

有了这种类型的服务器驱动网络,我是否可以在将所有内容转换为NIO方面找到一些好处?客户端通常只通过TCP套接字发送非常小的数据片段和几行文本。服务器很少也偶尔会向客户端发送较大的文件(图像、声音、视频)。在这个应用程序中使用IO/NIO还有其他想法吗?我想知道这是否可以通过消除最大创建线程数的瓶颈来扩展我的可伸缩性,即使它们只持续一秒钟左右


编辑:另请注意:如果玩家A等待超过30-60秒进行回合,则其回合将被没收。所以,我并不是在无限循环中永远戳服务器。充其量是每隔5秒几次。在一场比赛被罚之前,有一个上限是多少回合被罚。

我建议使用基于事件的方法,而不是这种同步方法


与在while循环中检查客户端数千次不同,您可以在事件循环中检查它,这样更高效、更可扩展。

为了避免最大线程瓶颈,您可以使用线程池。您可以通过使用NIO2异步IO类来实现这一点

class ConnectionConext {}

class Handler implements CompletionHandler<Integer,ConnectionConext > {
public void completed(Integer result, ConnectionConext conn) {
// handle result
}
public void failed(Throwable exc, ConnectionConext conn) {
// error handling
}
}

//using executor's thread pool
ExecutorService executor = ...
//consider other withFixedThreadPool, or withCachedThreadPool
AsynchronousChannelGroup group = AsynchronousChannelGroup
.withThreadPool(executor);

AsynchronousSocketChannel channel =
AsynchronousSocketChannel.open(group);

ByteBuffer buf = ByteBuffer.allocate(...);//consider to use ByteBuffer pool for better scalability
ConnectionConext conn = ..//some connection info that will be passed to completion handler.
Handler handler = ...

ch.read(buf, conn, handler);
class connectionNext{}
类处理程序实现CompletionHandler{
公共无效已完成(整数结果,ConnectionNext conn){
//处理结果
}
公共无效失败(可丢弃的exc,连接下一个conn){
//错误处理
}
}
//使用executor的线程池
executor服务executor=。。。
//考虑其他withFixedThreadPool或withCachedThreadPool
AsynchronousChannelGroup组=AsynchronousChannelGroup
.withThreadPool(执行人);
异步socketchannel通道=
异步socketchannel.open(组);
ByteBuffer buf=ByteBuffer.allocate(…)//考虑使用ByTeBuffe池以获得更好的可扩展性
ConnectionNext conn=..//将传递给完成处理程序的某些连接信息。
处理程序=。。。
总read(buf、conn、handler);

也考虑有用的东西。

如果需要限制并发,使用线程池而不是生成每个请求的线程(参见ExtutoService)。我看不出在您的用例中使用NIO有什么好处(大多数连接都是短期的)。但是,我会考虑使用另一个服务和网络优先级来服务那些大文件,服务器不能使用连接池。只有客户端才能使用连接池。您关于“不维护持久连接负载”的声明与您关于连接池的断言相矛盾。你的实际问题还不清楚,我的服务器实现了一个连接池,我说的持久性是指不是两个玩家将他们与服务器的连接保持到游戏结束,他们发送简短的请求,得到即时响应,然后结束连接/线程如果你的服务器实现了连接池,这是其他一些资源,比如数据库,您在这里还没有提到。它没有实现到客户端的连接池,这是您到目前为止提到的唯一一件事。您可能指的是与客户端的连接的集合。这不是同一件事。我在java服务器上使用BoneCP,每个连接产生一个新线程(很快在线程池中),其中一些最终完成了MySQL交互。我省略了一个重要的细节。如果一个玩家没有在30秒内完成回合,他们将失去该回合。所以玩家B只需检查是否轮到他们几次,每5秒左右一次。你所做的是正确的,而且“看起来”很有效。但是想象一下:您的服务器正在托管一百万个游戏(可能是两百万个玩家),因此,每五秒钟就会创建数百万个线程并执行数百万个操作(有时除了检查nothing之外什么都没有);你问的是可伸缩性。那么这比在200万玩家之间保持持久连接的可伸缩性强还是弱呢?这就是为什么我认为NIO可能在这里工作得更好,但问题仍然存在。刺激,还是持续?还忘了提到我将很快添加一个线程池。因此,真正的问题是,即使有了线程池,NIO在这方面是否仍比IO提供更多?我一醒来就去Grisley看看。NIO的异步IO更适合重载服务器应用程序。所以,如果每个客户机生成线程对于计划的工作负载来说非常昂贵,那么可以使用NIO线程池和可选的缓冲池的组合。