我正在编写一个使用NIO套接字的Java应用程序。它由3台服务器和一组客户端组成。客户端可以与服务器通信,而服务器可以与客户端和其他服务器通信。
服务器到服务器和客户端到服务器发送了Message
,这些序列已序列化为byte[]
阵列。每个Message
的第一个字节包含消息的大小,自然可以保证每个消息所包含的字节不超过127 (2^8 -1)
个字节。您可以将服务器和客户端的消息发送视为循环运行:
Message msg = new Message()
while (true) {
sendMessage(msg, server or client)
receiveMessage()
}
然后,实现使用ByteBuffer
。自然,就像在任何Java NIO实现中一样,每个服务器执行selector.select()
,然后检索SelectionKey
,以查看是否read
ing(调用handleRead()
方法),write
ing(调用handleWrite()
)还是需要处理accept
(调用handleAccept()
)。所有的handleXX
方法都采用有限的步骤,并且不会阻塞等待其他任何东西的时间。
[检索特定handleRead()
的数据(key
)时,我只是将数据存储在特定的映射Map<SelectionKey, List<byte[]>> readDataForKey;
中,然后遍历列表并提取所有已接收的消息。
但是,我注意到有时为某些handleRead
输入key
时,有数千条消息正在等待处理。我不知道为什么会这样吗?我希望handleRead
会看到几个消息,仅此而已。
事实上,数千条消息在被处理之前就已经积累了。这意味着什么?这是否意味着我的handleRead
或handleWrite
或NIO实现的其他部分花费的时间太长并且基础缓冲区已满?这是否意味着我偶尔会获得一次GC补偿(持续约10毫秒),并且同时缓冲区已满?这是否意味着我的代码在handleRead
中的运行速度可能会变慢,因此消息会累积?]
累积这么多消息是否正常?
您的消息很小。因此,本地发送缓冲区可能包含很多消息的可能性很高。是否曾经尝试在每条消息后都明确地刷新?以下内容可能会有所帮助:How to flush a SocketChannel in Java NIO?