2012-02-26 74 views
0

我已经编写了一个用于远程存储(iSCSI目标)的Java服务器。客户端可以通过发送携带数据有效载荷的数据包序列来写入数据。这些数据包包含一个固定长度的头(48字节),后跟一个可变长度的数据段。数据段的长度在标题中指定,可以认为是固定的(8KiB)。对于大型ByteBuffers,单独SocketChannel的并发读取()速度较慢

接收数据包是一个由两部分组成的过程。首先将标题读入一个大小为48字节的ByteBuffer。之后立即通过ByteBuffer.allocate(...)创建第二个ByteBuffer。第二个缓冲区的大小与头中指定的数据段长度相匹配。然后使用SocketChannel.read(ByteBuffer)方法将数据段读入第二个ByteBuffer。在简单情况下,此过程按预期工作 - 较大的数据段和较长的序列会提高IO速度。通过“简单情况”我的意思是有一个单线程使用阻塞SocketChannel来接收(和处理)数据包。但是,如果添加了具有自己的TCP连接和关联的SocketChannel的第二个线程,则SockerChannel.read(ByteBuffer)执行时间将增加到超过2.5ms,而客户端服务器正在发送32KiB写入命令(即4个连续的数据包)连接。这是增加了8倍到10倍。

我想强调,在这个阶段,两个线程不会共享任何资源,除了相同的网络接口卡。每个SocketChannel的读取缓冲区大小为43690字节(更大的大小对此现象没有任何影响)。

任何想法可能会导致这种情况或如何解决这个问题?

回答

1

...而客户机服务器发送32KiB写在两个连接的命令(即4个 连续数据分组)。

您能提供一些关于测试设置的细节吗?客户端是否将数据包连续发送到两个连接?然后根据设置增加可能是由客户驱动的。

它是本地主机设置(一台机器上的客户端和服务器)还是不同主机上的客户端和服务器?你有没有测试过?不要欺骗自己看到本地主机设置的执行时间增加,特别是如果只有一个cpu并且测试客户端也在本地运行,甚至可能是单线程的。

+0

客户端和服务器运行在不同的机器上,都有大量的空闲内核。但你是对的,错误似乎在于客户端。我一开始并没有看到这一点,因为在我的初步测量过程中,我对测试软件和切换版本的质量过于信服。我正在使用[iometer](http://www.iometer.org/)和Microsoft iSCSI Initiator,其中一个似乎会引入大的延迟,而不管它连接到哪个目标/服务器。 – andreas 2012-02-26 18:42:24