由于 "cannot open the connection" 错误,R 无法创建集群(多节点)

R cannot makeCluster (multinode) due to "cannot open the connection" error

我正在尝试并行 运行 R,它在本地主机上完美运行。现在我想切换到多节点设置并在同一网络中创建多个虚拟机。但是,当我尝试设置集群时,它失败并出现以下错误:

Error in socketConnection(master, port = port, blocking = TRUE, open = "a+b",  : 
cannot open the connection
Calls: <Anonymous> ... doTryCatch -> recvData -> makeSOCKmaster ->
socketConnection
In addition: Warning message:
In socketConnection(master, port = port, blocking = TRUE, open = "a+b",  :
ubuntu-r-node1:11056 cannot be opened

最小可重现示例:

library("parallel")
cl <- makeCluster(c(rep("192.168.42.26",2),rep("192.168.42.32",2)),outfile = "")

我也试过只在本地主机上打开套接字,但它也失败了(但本地主机上的集群只能工作),并出现相同的错误消息:

socketConnection("localhost", port = 11056, blocking = TRUE, open = "a+b")

仅当我添加 server = TRUE 选项时,socketConnection 才有效,但我不确定此选项是否适用于 makeCluster以及如何设置。

我全新安装了 Ubuntu 服务器 16.04,iptables 规则为空(全部接受),ssh 双向工作,所以我不知道为什么它不起作用。

看来,DNS 也应该双向工作。

例如,如果我的示例中的第一台主机 (192.168.42.26) 的名称为 'host1',第二台主机 (192.168.42.32) 的名称为 'host2',则两者都为

ssh host1

(来自主机 2)

ssh host2

(来自主机 1)

应该适用于 运行 R 集群。

当一个 worker 试图连接到 master 进程时,会发生 socketConnection 错误,可能是因为至少有一个 worker 无法解析 master 的主机名,即 "ubuntu-r-node1"例子。 master 的主机名默认使用 Sys.info()['nodename'] 确定,如果任何 worker 无法解析此名称,他们将无法创建与 master 的套接字连接,并且 makeCluster 将挂起.

这个问题的一个常见的work-around是使用makeCluster "master"选项来指定master正在执行的机器的IP地址。下面是一种使用 nsl 函数(在 Windows 上不可用)在主节点而不是工作节点上查找主节点主机名的方法:

cl <- makePSOCKcluster(c(rep('192.168.42.26', 2),
                         rep('192.168.42.32', 2)),
          master=nsl(Sys.info()['nodename']),
          outfile='')

通过为 worker 和 master 指定 IP 地址,DNS 问题就会少很多。在此示例中,master 将通过 ssh 连接到“192.168.42.26”和“192.168.42.32”来启动 worker,worker 将使用 socketConnection 返回值 [=17] 连接回 master =].

请注意,如果主机有防火墙,makeCluster "port" 选项也很重要,因为默认情况下,端口是在 11000 到 11999 范围内随机选择的。

如果此处涉及防火墙问题,则作为替代方案:

library("parallel")
workers <- c(rep("192.168.42.26",2), rep("192.168.42.32",2))
cl <- makeCluster(workers, outfile = "")

相当于:

cl <- makePSOCKcluster(workers, outfile = "")

您可以尝试使用:

library("future")
cl <- makeClusterPSOCK(workers, revtunnel = TRUE, outfile = "", verbose = TRUE)

后者将设置一个所谓的反向 SSH 隧道,它将是从 master 到 worker 的传出 SSH 连接的 "internal" 一部分。如果防火墙阻止工作人员连接回 master parallel::makePSOCKcluster(),例如,因为端口范围被阻止,那么 future::makeClusterPSOCK(..., revtunnel = TRUE) 可以解决该问题。 verbose=TRUE 输出应显示如下内容:

Starting worker #1 on '192.168.42.26': 'ssh' -R 11356:localhost:11356 192.168.42.26 "'Rscript' --default-packages=datasets,utils,grDevices,graphics,stats,methods -e 'parallel:::.slaveRSOCK()' MASTER=localhost PORT=11356 OUT= TIMEOUT=2592000 XDR=TRUE"
Waiting for worker #1 on '192.168.42.26' to connect back
Connection with worker #1 on '192.168.42.26' established
[...]

这表明,据此工人 192.168.42.26 所知,它正在连接回它认为 运行 在同一台机器上的主进程 (MASTER=localhost:11356) ,这是因为反向 SSH 隧道 (-R 11356:localhost:11356) 通过 SSH 连接将端口从该机器映射回主服务器。

如果这种反向隧道方法对您不起作用,我认为您必须向您的系统管理员询问有关哪些端口被阻止等的更多详细信息。

我希望这是有道理的。