Java胖客户端连接到本地主机时速度较慢,与远程快速连接

我在连接到自定义数据库服务器的(通常)延迟绑定的桌面Java应用程序中遇到问题。

当它在远程主机(Windows XP)上工作时,速度很快(大的表单在2秒内打开)。 当它运行在同一台主机上时,数据库处于打开状态(使用X11vnc和NX),速度非常慢(在20秒内打开相同的表单)。 服务器正在运行SuSE Linux Enterprise Server 10。

我检查了什么:

  • iptables是干净的(没有规则在filterrawmanglenat ,ACCEPT上的所有表)
  • 路由正常(只是默认路由和本地networking)
  • brtables甚至没有安装
  • tc是干净的
  • 对于64字节和1500字节的数据包,本地主机的ping延迟时间为0.007ms,远程主机的延迟时间为0.8ms左右
  • 环回吞吐量达到500MiB / s(使用netcattesting)
  • 不同的Java虚拟机(1.5和1.6)

在看atop时候,似乎没有任何瓶颈:

  • java和数据库进程的CPU利用率非常低(java:〜20%,数据库<5%),远程访问的CPU利用率是中等的(数据库为30%左右),服务器是四核2.66Ghz,客户端是一个酷睿2双核2.33Ghz,系统除了闲置
  • 在长查询期间几乎没有磁盘读取/写入(总共大约5-10次读取)

远程和本地运行之间唯一不同的是networking利用率,而本地进程以大约1200kbps的速率提取数据,远程站点以大约15Mbps的速度进行。

我目前正在努力重复我的硬件的问题,所以这些线上的任何提示也是受欢迎的。

编辑:改变从默认的16K的lo接口MTU到1500解决了这个问题。 这个问题在Debain lenny 64bit上被重复了。

我所得到的只是更多的debugging思路,没有特定的顺序。

  • 这真的是环回吗? 你尝试连接到服务器的networkingIP地址,而不是127.0.0.1? (这使用我系统上的回送接口,但是应该排除奇怪的DNS问题)
  • 在这段时间里, 系统负载是否高?(问题是否会导致系统负载高于所有单独的进程似乎是)?
  • 检查每个进程的netstat信息,如果客户端的Recv-Q很高,那么客户端进程不会定期从其套接字读取数据。
  • 尝试看tcpdump -i lo ,它可能有助于找出是否有一个明显的模式传输的数据包。
  • “vmstat 1”显示远程访问与本地访问版本(即在数据库服务器和Java客户端强制你交换的内存中的数据集)的行为显着不同?
  • 尝试增加回环设备上的MTU,我的默认值为16436.如果你做了很多小小的包,这将不会有太大的帮助。 小小包似乎有自己的问题。 我不是一个Java程序员,所以我不知道如何做,但尝试在连接上设置TCP_NODELAY(setsockopt系统调用)。 这似乎有一个货物邪教跟随,但据推测,如果沟通是单向的,客户端将更加定期地回应TCP ​​ACK,并保持数据stream动。
  • 另一个尝试调整: echo 1 > /proc/sys/net/ipv4/tcp_low_latency
  • 在使用setsockopt时,看看如果增加客户端的发送和接收缓冲区会发生什么?
  • 你是不是在使用某种古老的2.2内核? 根据2.4 TODO,2.3.x显然有一些巨大的回送错误
  • 也许在客户端(或Java)有一个错误,你有一个单独的Linux系统运行完全相同的客户端与相同的Java运行时?

这听起来很奇怪,但是前一阵子对我来说很奏效。
检查/ etc / hosts文件以使您的主机名与localhost一致,或者添加一个指向127.0.0.1或一个监听的。

为了消除X11vnc和NX作为延迟的可能原因,我会编写一个控制台模式的非GUI Javatesting程序,执行数据库查找或testing交易和时间,在PC上和服务器上运行的应用程序(例如使用SSH / Putty调用它)。

很长一段时间:如果JDBC驱动程序正在使用(例如,用于日志logging),如果DNSconfiguration不正确,软件可能会挂起等待DNSparsing超时,我也会检查反向DNSparsing。 在Java应用程序中如何configurationDBMS位置?

你有没有尝试连接到127.0.0.1而不是本地主机? 这有几件事情。 避免疯狂的DNS问题是其中之一,但也有很多客户端看到“本地主机”,然后决定不使用networking,而是使用一些本地套接字。 这可能是这个自动技术开关,正在杀死你的应用程序。 几个程序做这个主要的像mysql一样。 通过IP使用本地主机环回地址迫使他们实际使用networking套接字。

我最喜欢的工具是像这样的问题。 你可以简单地对客户端进行压缩,并在做一些事情(阻塞调用,如连接或读取)之后暂停。 如果有某种事件循环模糊了暂停,您可以尝试将这些系统调用过滤出来,或者可以打开计时选项以将整个输出保存在文件中。 另一个诀窍就是等到它“结束”,不pipe是什么东西,然后打到^ C,所以你可以看看发生了什么事情,把它从昏迷中解脱出来。

原来是应用程序中的一个错误。 对于小型MTU,TCP将数据包分割并且不会暴露该错误。 回环上的MTU高,这个错误就performance出来了。