以下是我的设置:VMWare ESXi 4.0 上的两个 CentOS 5.2 盒子。第一个盒子的 ip 是 eth0 上的 192.168.22.52 和 eth1 上的 192.168.99.1。第二个盒子在 eth0 上运行 PostgreSQL 8.3,ip 为 192.168.99.2。以下是 iptables框1,对于 box2 请参阅下面的注释。
我已经在 box1 上设置了端口 5432 转发,并且能够通过 Vista 笔记本上的 pgAdminIII 或 psql 连接到 box2 上的 PostgreSQL(192.168.22.1,此子网中没有其他盒子,它有自己的交换机并且物理上是隔离的)。我连接的数据库有两个模式,一个“较小”(基本上只有一个表),另一个较大(大约 30 个表、100 个函数等)。因此,我能够使用较小的模式(浏览表等),但是当我尝试扩展较大的模式时 - pgAdminIII 会冻结 20 分钟左右。
PostgreSQL 日志显示有一个查询耗时太长:
2009-06-04 21:04:46 EEST LOG: 00000: duration: 493578.874 ms statement:
SELECT pr.oid, pr.xmin, pr.*, format_type(TYP.oid, NULL) AS typname,
typns.nspname AS typnsp, lanname, proargnames, proconfig,
pg_get_userbyid(proowner) as funcowner, description
FROM pg_proc pr
JOIN pg_type typ ON typ.oid=prorettype
JOIN pg_namespace typns ON typns.oid=typ.typnamespace
JOIN pg_language lng ON lng.oid=prolang
LEFT OUTER JOIN pg_description des ON des.objoid=pr.oid
WHERE proisagg = FALSE AND pronamespace = 2200::oid
AND typname <> 'trigger'
ORDER BY proname
box1 和 box2 都是开发箱的克隆,原始网络结构不同 - box2 无需端口转发即可直接访问,并且访问数据库没有任何问题。
现在,如果我通过 box2 或“原始”机器上的 psql 运行上述查询,或者从 box1 连接到 box2,它会立即执行。
在查询运行期间,box2 上的 tcpdump 定期显示:
12:45:39.770609 IP 192.168.99.2.postgres > 192.168.22.1.49484: . 8760:10220(1460) ack 1 win 54
12:45:39.968496 IP 192.168.22.1.49484 > 192.168.99.2.postgres: . ack 10220 win 16425
12:45:39.968541 IP 192.168.99.2.postgres > 192.168.22.1.49484: . 10220:11680(1460) ack 1 win 54
12:45:39.968574 IP 192.168.99.2.postgres > 192.168.22.1.49484: . 11680:13140(1460) ack 1 win 54
12:45:39.969250 IP 192.168.22.1.49484 > 192.168.99.2.postgres: . ack 13140 win 16425
12:45:39.969275 IP 192.168.99.2.postgres > 192.168.22.1.49484: . 13140:17520(4380) ack 1 win 54
12:45:39.969408 IP 192.168.22.52 > 192.168.99.2: ICMP 192.168.22.1 unreachable - need to frag (mtu 1500), length 556
除此之外,我没有看到太多流量。所有 ethN 接口上的 MTU 都是 1500。从笔记本电脑执行 ping -l 1472 -f 192.168.99.1 没有任何问题。
我怀疑我遗漏了有关 iptables 或网络设置的某些信息,希望得到您的建议。
答案1
可以尝试以下操作:
首先验证您的网络是否正常运行。假设您已管理交换机,请查看接口统计信息以查找速度/双工不匹配或 MTU 不匹配。如果出现任何运行错误,请考虑检查/更换电缆(例如:尝试通过 Cat5 而不是 Cat5e 运行 GigE 可能会带来麻烦)。
运行一些测试来证明您可以在两台机器之间以及与外部机器之间获得线速传输;netcat、ftp 或 http 传输是一个很好的开始(scp 可能会受到 CPU 限制,因此可能不是最好的测试)。
在 Postgres 服务器上本地测试相同的查询。如果它在适当的时间范围内完成,您就知道这不是数据库的问题。如果它没有完成或花费“太长时间”,那么您有一个错误的查询或其他数据库问题需要调试。一定要考虑存储 I/O 方面的问题;您可能已经饱和了磁盘能够提供的内容。检查 VMware 性能图以确认/否认。
假设此方法有效,请禁用防火墙并从“box1”对 postgres 服务器运行相同的查询。如果此方法有效,则 VM->VM 连接可能没有问题。
假设此方法有效,请重新启动防火墙并再次测试。如果此方法有效,则问题可能出在该主机之外,只需调试交换机或外部主机即可。
祝你好运。
答案2
您遇到了 MTU 问题,但我不确定原因。我正在努力弄清楚这里的虚拟拓扑。
那么,您的 Windows Vista 笔记本电脑是连接到“本地”网络,还是 Internet 网络?
我假设您的 Windows Vista 笔记本电脑已连接到互联网,并且您正在访问“盒子 1”的外部 IP 地址,以使用端口 5432 上的端口转发到达“盒子 2”。如果是这样,当您尝试执行以下操作时会得到什么结果:
ping -l 1472 -f <盒子 1 的 IP 地址>
编辑:好的——非常好。如果可以的话,请在“box 1”和“box 2”上运行“ifconfig”,并检查每个以太网接口上的 MTU 值。它们都应该是 1500。(我只是想弄清楚为什么“box 1”告诉“box 2”它无法分割发往您的笔记本的 556 字节数据报……)
编辑:哇哦。好吧——太疯狂了。
如果要求不太高的话,您能否将您的 iptables 配置内容(或其链接)发布到问题中?(我开始被难住了。您所描述的是我经常做的事情,但我不确定它是如何分解的。)
编辑:现在回到你身边。好的。我现在对这个感到困惑。iptables 配置看起来不应该导致任何问题。我确实看到您正在将 UDP 5432 转发到“box 2”。你不需要转发它——Postgres 只使用 TCP。不过,这不会造成任何损害。
在您等待的 20 分钟内,您是否看到 Vista 笔记本和“box 2”之间的流量在流动?每次连接时都能重现这种情况吗?
这并不是说这会产生很大的不同,但在“box 1”的 FORWARD 链上,我通常会将接受 RELATED、ESTABLISHED 设置的数据包的规则设为链中的第一条规则(以缩短处理过程)。不过,我认为这不会对您产生任何重大的性能影响。
我讨厌不知道问题的答案。这会让我彻夜难眠。
答案3
是否有可能其中一台机器试图不恰当地使用 IPv6?也就是说,您是否已确保在不应该使用 IPv6 的所有地方都将其关闭,并且如果使用 IPv6,是否已正确配置?