我正在ssh
macOS 上运行,以将本地 Unix 域套接字的连接重定向到另一台计算机上的域套接字。调用的命令行ssh
大致如下:
$ ssh -nNT -L /var/run/some.socket:/var/run/some.socket -o TCPKeepAlive=yes \
-o ServerAliveCountMax=10 -o ServerAliveInterval=60 user@destination
在执行一些负载测试后,我发现有时某些客户端连接会失败,并且在检查日志时,我发现ssh
连接失败的同时输出以下错误:
channel 41: open failed: connect failed: open failed
channel 44: open failed: connect failed: open failed
channel 47: open failed: connect failed: open failed
channel 49: open failed: connect failed: open failed
channel 51: open failed: connect failed: open failed
channel 59: open failed: connect failed: open failed
channel 62: open failed: connect failed: open failed
channel 64: open failed: connect failed: open failed
负载测试参数是运行 100 个并发连接(连接、发送一些数据、接收一些数据、断开连接,总共要执行 10,000 个连接。)
观察到的行为是,在测试开始时,第一组连接很快创建,很少有连接因上述错误而失败。失败的次数因运行而异,但通常在几次到十几次之间。大多数失败往往发生在测试开始时,但有时会发生在测试后期(即完成前 100 次之后)。
SO 上具有类似描述的其他帖子似乎涵盖了使用localhost
和解决方法来使用的问题127.0.0.1
,这使得它不相关,因为它不是 TCP/IP 套接字。另外,destination
上述命令中的部分已经被指定为IP地址。
有点不知道如何解决和追踪问题。我尝试使用-vvv
来获取ssh
操作的详细转储,但没有任何成果(相关通道的所有日志都是套接字设置为非阻塞)。
请注意,调用是ssh
从脚本完成的,并且调用之前ulimit -n 1024
应提供足够多的文件描述符以可用于服务所有套接字。
答案1
channel 41: open failed: connect failed: open failed
此错误消息意味着远程 SSH 服务器无法执行 TCP 转发请求,因为它无法连接到隧道的目标。消息的最后一个“打开失败”部分是来自远程 SSH 服务器的错误消息。
当您使用端口转发运行 SSH 时,端口转发的工作方式如下:
- 本地 ssh 客户端侦听本地端口上的 TCP 连接(在您的情况下为 /var/run/some.socket )。
- 当发起者连接到本地端口时,ssh 客户端会向服务器发送对“direct-tcpip”通道的请求。该请求包括隧道的目标(在您的情况下,远程系统上的 /var/run/some.socket )。
- 远程 SSH 服务器与隧道目标建立 TCP 连接。
- 本地 ssh 客户端和远程 ssh 服务器在各自的 TCP 连接和 direct-tcpip 通道之间双向中继数据。
在您的情况下,ssh 服务器在第 3 步失败,因为由于某种原因它无法连接到隧道的目标。
您应该检查远程服务器上的 ssh 日志。 SSH 服务器进程可能已记录一条消息,说明失败的原因。除此之外,您说这是在负载测试期间间歇性发生的,所以我会研究与负载相关的服务器端问题。我想到了几种可能性:
- 远程系统上侦听 /var/run/some.socket 的应用程序处理连接请求的速度不够快,并且正在积压。
- SSH 服务器进程遇到某种资源限制(例如,打开的文件描述符的数量)