折腾了十几个小时,终于让一个spark任务可以完整地跑在分布式集群上了。以下是我遇到的各种问题和我的解决办法:
最开始有个什么问题我忘了,不过解决办法是开放slave的50010端口。
- 提交spark任务之后没反应,在web ui里也看不见任务被提交了
请尝试在提交任务的时候显式指定资源分配,例如:
--executor-cores 2 \
--executor-memory 2g \
--driver-memory 2g \
--num-executors 3 \
--conf spark.network.timeout=600s \
--conf spark.executor.heartbeatInterval=60s \
--conf spark.executor.memoryOverhead=1g \
2.提交任务之后报错:ARN TaskSchedulerImpl: Initial job has not accepted any resources; check your cluster UI to ensure that workers are registered and have sufficient resources
这个问题有可能是因为slave的excutor要连接到Driver的地址是master节点上的一个随机端口,由于该端口可能没有开放,所以会失败。我的解决办法是在提交的时候显式设定端口:
--conf spark.driver.bindAddress=192.168.0.41 \ (用master的内网ip)
--conf spark.driver.host=master \
--conf spark.driver.port=40000 \
--conf spark.driver.blockManager.port=40001 \
--conf spark.rpc.driver.port=40002 \
记得还要在master云服务器的安全组里放开对应的端口。(比如示例是40000,40001,40002)
3.开始运行spark任务的时候,卡在某个地方,报这样的错:
org.apache.spark.shuffle.FetchFailedException: Failed to connect to /192.168.0.187:38170
...
Caused by: io.netty.channel.AbstractChannel$AnnotatedNoRouteToHostException: No route to host: /192.168.0.187:38170
核心的的报错代码是Failed to connect to 某个slave的内网IP,No route to host 某个slave的内网IP
这个问题的主要原因是,slave在注册到master的spark上的时候,是用内网IP注册的,这导致slave之间进行通信的时候是用的内网IP,如果slave是不同网络下的云服务器,就不可能通过内网IP访问到其他的slave。
第一个解决办法是让slave用公网IP注册到master上,但我试了很多办法都没有成功(包括但不限于,加spark_local_ip,改各种参数,host里改公网IP之类的),如果可以做到,还是推荐用这个办法。
第二个解决办法对于服务器是在一个区域里的,我更推荐。我也是在之前的Issue里找到的。简单地说,就是要让各个服务器配置在一个内网里,如果大家都在一个内网,那就可以用内网地址进行访问了,同时这样会加快任务的运行速度,具体如何配置请看附件。
云服务器配置到一个内网.pdf
附件的前提是各个云服务器要在一个区域,如果不在一个区域,那么就要做些复杂的操作,需要创建新的云服务器,保证这些云服务器在一个区域,同时为了不重新做以前的事,要把旧服务器的配置完全复制过来。具体请按照这个教程执行云服务器的跨区域镜像复制:https://support.huaweicloud.com/usermanual-ims/ims_01_0332.html
大致操作如下:创建一个新的云服务器,保证云服务器都在一个区域里(可用区无所谓),对原本的服务器进行镜像生成,选择完整镜像。这里会让你买一个云备份服务器,选择按需计费即可,有学校发的代金卷不用怕花钱,而且搞完所有操作后直接删了就行。买好新服务器之后,同时做好原服务器的镜像之后,就请按照上面那个教程把镜像跨区域复制(提交委托的时候请用旧版控制台,不然找不到IMS)
镜像跨区域复制成功后,在新的云服务器上选择切换操作系统,镜像选择私有镜像,也就是才复制过来的镜像。操作完之后,新的服务器的配置就和老的基本上差不多了(可以ssh到新的云服务器查看一下有没有hadoop这个用户,有就说明镜像过来了),但还需要更改一些东西。
因为新的服务器的IP变化了,所以请修改host文件里的IP地址。接下来尝试是否可以ssh到各个slave,以及slave可不可以ssh回 master,如果不可以,请用ssh-keygen -R 指令删掉以前的ssh记录,具体删什么可以拿错误代码问ai。
当新的云服务器之间可以做到互相ssh之后,就再试试hadoop和spark集群可不可以开起来,再试着执行之前的sprak任务,看看是不是还是卡在原来的地方,卡在原本的位置说明是对的,配置完全被镜像过来了。
接下来就请跟着附件把同一个区域的云服务器配置到一个内网里,配置完之后再提交spark任务,应该就可以正常跑起来了。(而且是通过内网跑的,所以会更快)
如果还不可以,有可能也和第二个问题一样,slave之间的通信是随机端口,此时请显示指定端口:
--conf spark.blockManager.port=39000
同时在slave的安全组上放开对应端口
我觉得实验开始创建云服务器的时候,大家最好都选择同一个区域的云服务器,主要为了防止我这种情况。
折腾了十几个小时,终于让一个spark任务可以完整地跑在分布式集群上了。以下是我遇到的各种问题和我的解决办法:
最开始有个什么问题我忘了,不过解决办法是开放slave的50010端口。
请尝试在提交任务的时候显式指定资源分配,例如:
这个问题有可能是因为slave的excutor要连接到Driver的地址是master节点上的一个随机端口,由于该端口可能没有开放,所以会失败。我的解决办法是在提交的时候显式设定端口:
记得还要在master云服务器的安全组里放开对应的端口。(比如示例是40000,40001,40002)
核心的的报错代码是
Failed to connect to 某个slave的内网IP,No route to host 某个slave的内网IP这个问题的主要原因是,slave在注册到master的spark上的时候,是用内网IP注册的,这导致slave之间进行通信的时候是用的内网IP,如果slave是不同网络下的云服务器,就不可能通过内网IP访问到其他的slave。
第一个解决办法是让slave用公网IP注册到master上,但我试了很多办法都没有成功(包括但不限于,加spark_local_ip,改各种参数,host里改公网IP之类的),如果可以做到,还是推荐用这个办法。
第二个解决办法对于服务器是在一个区域里的,我更推荐。我也是在之前的Issue里找到的。简单地说,就是要让各个服务器配置在一个内网里,如果大家都在一个内网,那就可以用内网地址进行访问了,同时这样会加快任务的运行速度,具体如何配置请看附件。
云服务器配置到一个内网.pdf
附件的前提是各个云服务器要在一个区域,如果不在一个区域,那么就要做些复杂的操作,需要创建新的云服务器,保证这些云服务器在一个区域,同时为了不重新做以前的事,要把旧服务器的配置完全复制过来。具体请按照这个教程执行云服务器的跨区域镜像复制:https://support.huaweicloud.com/usermanual-ims/ims_01_0332.html
大致操作如下:创建一个新的云服务器,保证云服务器都在一个区域里(可用区无所谓),对原本的服务器进行镜像生成,选择完整镜像。这里会让你买一个云备份服务器,选择按需计费即可,有学校发的代金卷不用怕花钱,而且搞完所有操作后直接删了就行。买好新服务器之后,同时做好原服务器的镜像之后,就请按照上面那个教程把镜像跨区域复制(提交委托的时候请用旧版控制台,不然找不到IMS)
镜像跨区域复制成功后,在新的云服务器上选择切换操作系统,镜像选择私有镜像,也就是才复制过来的镜像。操作完之后,新的服务器的配置就和老的基本上差不多了(可以ssh到新的云服务器查看一下有没有hadoop这个用户,有就说明镜像过来了),但还需要更改一些东西。
因为新的服务器的IP变化了,所以请修改host文件里的IP地址。接下来尝试是否可以ssh到各个slave,以及slave可不可以ssh回 master,如果不可以,请用ssh-keygen -R 指令删掉以前的ssh记录,具体删什么可以拿错误代码问ai。
当新的云服务器之间可以做到互相ssh之后,就再试试hadoop和spark集群可不可以开起来,再试着执行之前的sprak任务,看看是不是还是卡在原来的地方,卡在原本的位置说明是对的,配置完全被镜像过来了。
接下来就请跟着附件把同一个区域的云服务器配置到一个内网里,配置完之后再提交spark任务,应该就可以正常跑起来了。(而且是通过内网跑的,所以会更快)
如果还不可以,有可能也和第二个问题一样,slave之间的通信是随机端口,此时请显示指定端口:
--conf spark.blockManager.port=39000同时在slave的安全组上放开对应端口
我觉得实验开始创建云服务器的时候,大家最好都选择同一个区域的云服务器,主要为了防止我这种情况。