当前位置: 首页 > 知识库问答 >
问题:

Java NIO - 消息的积累

咸星波
2023-03-14

我正在编写一个使用NIO套接字的Java应用程序。它由3台服务器和一组客户端组成。客户端可以与服务器通信,服务器可以与客户端和其他服务器通信。

服务器到服务器和客户端到服务器发送序列化为< code>byte[]数组的< code >消息。每个< code >消息的第一个字节包含消息的大小,自然保证每个消息不包含超过< code>127 (2^8 -1)字节。您可以将服务器和客户端的消息发送视为循环操作:

Message msg = new Message()
while (true) {
    sendMessage(msg, server or client)
    receiveMessage()
}

然后,该实现使用<code>ByteBuffer</code>。自然,就像在任何JavaNIO实现中一样,每个服务器都执行<code>选择器。select(),然后检索SelectionKeys,以查看是否需要处理读取ing(调用 方法)、 写入handleWrite())或 handleAccept())。所有 handleXX方法都会执行有限的步骤,并且不会阻塞等待其他操作。

当检索特定的数据(handleRead())时,我只将数据存储在特定的映射中

然而,我注意到,有时当输入某个< code >键的< code>handleRead时,会有成千上万的消息等待处理。我不明白为什么会这样?我希望< code>handleRead能看到几条消息,仅此而已。

事实上,成千上万的消息在被处理之前就被累积起来了。这是什么意思?这是否意味着我的HandleReadrHandleWrit或NIO实现的其他部分花了太长时间,底层缓冲区就满了?这是否意味着偶尔我得到一个GC偶数(约10毫秒),同时缓冲区也满了?这是否意味着我在HandleReadr中的代码可能很慢,因此消息会被累积起来?

这么多消息堆积起来正常吗?

共有2个答案

景宏富
2023-03-14

我无法发表评论,所以我会在这里添加我的评论...


1.单客户端和单服务器是否出现问题?仅2台服务器(即无客户端)

单个服务器有多个客户端?

关于:

这是否意味着我的handleRead或handleWrite或NIO实现的其他部分花费的时间太长

您可以添加一些日志来测量您在那里花费的时间(或者如果您想更进一步,您可以使用MAT或VisualVM,它也可以提示您是否由于GC而被延迟)

龙正初
2023-03-14

你的消息很小。因此,发送和接收缓冲区可以包含大量消息。如果您没有明确指定发送和接收缓冲区的大小,TCP堆栈将尽最大努力优化大小,以便通过网络进行高效传输。虽然大多数Linux发行版的默认大小约为128KB,但最大大小可能为数兆字节(例如,在延迟非常高的网络上)。因此,单个handleRead可以轻松地看到数百或数千条消息。TCP尝试尽可能好地使用网络的带宽。在接收缓冲区中看到大量消息并不意味着您的接收器过载。TCP甚至可以避免接收器过载。衡量您的html" target="_blank">系统是否“过载”的唯一方法是测量发送消息所需的时间(例如,在消息发送之前将其排队并测量其大小)

在某些情况下,手动优化缓冲区大小是有意义的(例如,延迟非常高的网络),但大多数情况下,TCP堆栈在这方面做得很好。在极少数情况下,禁用Nagle的算法(例如Telnet和SSH)以最小化用户输入的反应时间是有意义的,但大多数情况下,绝对不需要手动干预。让TCP做它的工作,这是为了高效传输而优化,并避免接收器过载。

 类似资料:
  • 我在两个线程中使用一个SocketChannel,一个线程用于发送数据,另一个线程用于接收数据。 线程1:使用上述socketchannel写入数据 线程2:使用相同的socketchannel读取数据 我没有在socketchannel中使用任何选择器,因为我需要写和读是异步的(使用两个不同的线程) 问题:当连接丢失时,socketchannel。write()和socketchannel。re

  • 消息组件为你的App提供了可视评论和消息系统。 消息组件布局 ... <div class="page"> <div class="page-content messages-content"> <div class="messages"> <!-- 时间戳 --> <div class="messages-date">Sunday, Feb 9 <spa

  • Unread message count(未读消息统计) GET /user/counts 响应: Status: 200 OK { "user": { // 用户相关 "following": 1, // 用户关注者新增(粉丝新增)数量 "liked": 0, // 被点赞数 "commented": 0, // 被评论数 "system": 0,

  • 公众号消息分为 服务端被动回复消息 和 客服消息 两个场景。 需要注意的是两个场景的消息虽然类似,但是结构却有些差异,比如服务端使用 XML 结构,而客服消息使用 JSON 结构,且同样类似的消息类型,结构和名称都有些许差异,在使用时请勿混淆。 服务端消息结构 当你接收到用户发来的消息时,可能会提取消息中的相关属性,参考: 请求消息基本属性(以下所有消息都有的基本属性): - `ToUserN

  • 我把微信的 API 里的所有“消息”都按类型抽象出来了,也就是说,你不用区分它是回复消息还是主动推送消息,免去了你去手动拼装微信的 XML 以及乱七八糟命名不统一的 JSON 了。 在阅读以下内容时请忽略是 接收消息 还是 回复消息,后面我会给你讲它们的区别。 消息类型 消息分为以下几种:文本、图片、视频、声音、链接、坐标、图文、文章 和一种特殊的 原始消息。 另外还有一种特殊的消息类型:素材消息

  • 注:内容翻译自官网文档 Messages 给出一个简单的消息定义: message Foo {} protocol buffer 编译器生成名为 Foo 的类,实现 Message 接口。这个类被定义为 final, 不容许任何子类。Foo 继承自 GeneratedMessage, 但是这个可以认为是实现细节。默认, Foo 用为实现最大速度的特别版本来覆盖很多 GeneratedMessag