【问题标题】:Is this network design a candidate for improved preformance from non-blocking NIO? [closed]这种网络设计是否可以提高非阻塞 NIO 的性能? [关闭]
【发布时间】:2013-06-08 01:35:17
【问题描述】:

我正在开发一款通用的回合制游戏,目前它的运作方式如下: 使用 boneCP(连接池)、MySQL 数据库、java 服务器、android 客户端,以及即将推出的线程池。

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

每个客户端不是维护大量持久(持久)连接,而是每隔 (x) 间隔简单地戳一下服务器,并询问是否轮到他们了。如果不是,它什么也不做。如果是,它可以输入并将其发送到服务器。

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

编辑:另请注意:如果玩家 A 等待超过 30-60 秒才能轮到他们,那么他们的回合将被放弃。所以这并不是说我可能永远在无限循环中戳服务器。充其量是5秒的间隔几次。在游戏没收之前有多少回合没收是有上限的。

【问题讨论】:

  • 如果您需要限制并发,请使用线程池而不是为每个请求生成一个线程(请参阅 ExecutorService)。我看不出在您的用例中使用 NIO 有什么好处(大多数连接都是短暂的)。但是,我会考虑使用其他服务和网络优先级来处理这些大文件
  • 服务器不能使用连接池。只有客户端可以使用连接池。您关于“不维护大量持久连接”的陈述与您关于连接池的断言相矛盾。您的实际问题仍然模糊不清,
  • 我的服务器实现了一个连接池,我的意思是持久的,而不是两个玩家保持与服务器的连接直到他们的游戏结束,他们发送简短的请求以获得即时响应然后结束连接/线程
  • 如果你的服务器实现了一个连接池,它是指向你这里还没有提到的一些其他资源,比如一个数据库。它没有实现到客户端的连接池,这是您迄今为止唯一提到的。可能您的意思是与客户端的连接的collection。这不是一回事。
  • 我在 java 服务器上使用 BoneCP,它为每个连接生成一个新线程(很快在线程池中),其中一些最终会进行 MySQL 交互。

标签: java multithreading io connection-pooling nio


【解决方案1】:

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

您可以在更高效和可扩展的事件循环中检查客户端,而不是在 while 循环中检查数千次。

【讨论】:

  • 我遗漏了一个重要的细节。如果玩家在 30 秒内没有轮到他们,则他们输掉该回合。所以玩家 B 只需要检查是否轮到他们几次,每 5 秒左右一次。
  • 您所做的是正确的并且“似乎”有效。但是想象一下:您的服务器正在托管一百万个游戏(可能是两百万个玩家),因此,每五秒内创建了数百万个线程并执行了数百万个操作(有时只是检查什么都没有);您是在询问可扩展性。
  • 那么,与维持 200 万玩家之间的持久连接相比,这或多或少具有可扩展性吗?这就是为什么我认为 NIO 在这里可能会更好地工作,但问题仍然存在。刺激,还是坚持?
【解决方案2】:

为了避免最大线程瓶颈,您可以使用线程池。您可以通过使用 NIO 2 异步 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);

还可以考虑 Grizzly Project 获取有用的东西。

【讨论】:

  • 另外忘了提一下,我也会尽快添加线程池。所以真正的问题是即使有了线程池,NIO 是否仍然提供比 IO 更多的功能?我一醒来就去看看格里斯利。
  • NIO 的异步 IO 更适合重负载的服务器应用。因此,如果每个客户端生成线程对于计划的工作负载来说非常昂贵,那么请结合使用 NIO 线程池和可选的缓冲池。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-01
  • 1970-01-01
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多