我编写了一个用于远程存储的 Java 服务器(一个 iSCSI 目标)。客户端可以通过发送携带数据有效负载的数据包序列来写入数据。这些数据包由一个固定长度的报头(48 个字节)和一个可变长度的数据段组成。数据段的长度在标头中指定,可以认为是固定的(8KiB)。
接收数据包是一个两部分的过程。首先将标头读取到大小为 48 字节的 ByteBuffer 中。之后立即通过 ByteBuffer.allocate(...) 创建第二个 ByteBuffer。第二个缓冲区的大小与标头中指定的数据段长度相匹配。然后使用 SocketChannel.read(ByteBuffer) 方法将数据段读入第二个 ByteBuffer。在简单的情况下,此过程按预期工作 - 更大的数据段和更长的序列会提高 IO 速度。“简单情况”是指有一个线程使用阻塞的 SocketChannel 来接收(和处理)数据包。但是,如果添加第二个具有自己的 TCP 连接和关联的 SocketChannel 的线程,则 SockerChannel.read(ByteBuffer) 执行时间会上升到 2.5 毫秒以上,而客户端服务器在两个连接上都发送 32KiB 写命令(即 4 个连续的数据包)。这增加了 8 到 10 倍。
我想强调的是,在这个阶段,除了同一个网络接口卡之外,两个线程不共享任何资源。每个 SocketChannel 的读取缓冲区大小为 43690 字节(较大的大小对这种现象没有任何影响)。
任何想法可能导致此问题或如何解决此问题?