hadoop使用过程中的一些问题记录

抽时间记录了一下之前在做大数据平台时候一些问题的记录和解决思路,设计节点性能排查,vpn server部署,以及hadoop生态各个组件的问题记录。

集群节点性能问题排查思路

  • uptime (查看系统负载)

  • top (查看整体cpu idle情况)

  • free -m (查看内存使用情况)

  • iostat
    iostat -x -k 查看磁盘io情况(这里会显示cpu总核数,以及io空闲情况)
    iostat -dmx 2 (每两秒打印一次磁盘情况)
    如果有io util 100%的情况, 可进一步使用iotop进行分析

  • vmstat
    vmstat 2 (每2s查看一下系统详情)参考

  • ss
    ss -s 查看socket情况
    ss -t - l (查看全部监听的tcp socket)
    ss state all sport = :ssh (列出所有端口为22的连接)
    ss state al dst 74.125.0.0/16 (列出所有到达74.125.0.0./16这个子网的连接)
    ss详细说明
    ss内容解释

  • perf
    perf top (查看cpu使用)参考
    抓取一分钟的采样,进行负载分析:
    perf record -a -g -F 1000 sleep 60
    perf report
    对指定pid做负载分析:
    perf top -p pid
    按类型进行统计:(按pid,命令名进行统计)
    perf top -s pid, comm

  • pidstat

    pidstat 3 10 (每隔3s统计一次进程cpu资源使用, 总共统计10次)
    pidstat -r (增加进程内存使用统计)
    pidstat -r -p 1 1 ( -p 指定pid,查看特定进程的内存统计)

  • 利用awk统计tcp socket情况

    1
    2
    3
    4
    #统计不同类型的socket个数
    netstat -na | awk '/^tcp/ {++Arr[$NF]} END {for(item in Arr) print item, Arr[item]}'
    # 统计每个用户的进程占了多少内存
    ps aux | awk 'NR!=1{a[$1]+=$6;} END { for(i in a) print i ", " a[i]"KB";}'

openvpn 服务部署

默认情况下,Hadoop集群均不会开放外网,可以通过部署openvpn server,通过这个方式去访问内网的集群服务

  • server端部署

    1
    2
    3
    4
    1: 创建一个云主机,并为防火墙开放1194端口,选择udp协议
    2:从github下载自动部署脚本(使用其中的openvpn-install.sh脚本)
    地址:https://github.com/Nyr/openvpn-install
    3. 直接运行 openvpn-install.sh脚本,根据提示完成安装,创建server的同时可以生成一个客户端文件
  • client

    1
    2
    3
    安装完ovpn server后,再次执行sh openvpn-install.sh 可以看到创建客户端用户的选项。 也可以直接使用server部署时生成的客户端用户文件,然后拷贝到本地。
    window可以直接在openvpn官网下载客户端,选择自己操作系统对应的版本:https://openvpn.net/community-downloads/
    mac上可以去安装Tunnelblick:https://tunnelblick.net/downloads.html

zk

  • zookeeper snap文件占用大量存储问题修复

    1
    2
    3
    4
    5
    6
    #zoo.cfg增加如下配置,重启zk服务

    # 指定清理频率,单位是小时,默认是0,表示不开启自己清理功能。
    autopurge.purgeInterval=24
    # 和上面的参数搭配使用,指定需要保留的文件数目,默认是保留3个。
    autopurge.snapRetainCount=5
  • 磁盘usage 100%造成zk 异常
    如果磁盘空间被用尽后,节点的zk server会异常,此时即使清理了磁盘空间后,zk重启可能还是会报错,解决办法: 进入zk配置的dataDir目录, mv version-2 version-2-bak 后重启zk server服务即可

hdfs

  • 加快hdfs datanode节点退役速度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
生产中的hdfs 存储节点动辄几十上百TB的数据, 如果不进行调整,一次节点退役数据迁移要好多天,调整hdfs-site.xml配置进行优化:
#hdfs-site.xml
<property>
<name>dfs.namenode.replication.max-streams</name>
<value>32</value>
</property>
<property>
<name>dfs.namenode.replication.max-streams-hard-limit</name>
<value>200</value>
</property>
<property>
<name>dfs.namenode.replication.work.multiplier.per.iteration</name>
<value>200</value>
</property>
  • 节点磁盘使用不均匀问题
    线上的datanode 节点,往往多是挂载了多块磁盘,磁盘故障也是不可避免的问题,当故障磁盘进行更换后,这个节点就可能出现3块磁盘使用率80%, 新更换磁盘使用率0%的情况。到了hadoop3.0,多了一个新特性,就是支持磁盘间的数据均衡,但是对于hadoop 2.x,就只能流口水了。
    推荐方案:对这个节点做hdfs datanode退役,重新格式化所有磁盘后重新进行节点上线
    高风险方案(不推荐): 先关闭节点datanode服务,手动移动finalized block到其他磁盘,注意保持文件相对目录和文件名不变:
    eg: mv /data/dfs/dn/current/BP-1444476161-10.10.194.99-1494993066456/current/finalized/subdir99/subdir120/* /data3/dfs/dn/current/BP-1444476161-10.10.194.99-1494993066456/current/finalized/subdir99/subdir120/

hbase

  • 使用phoenix操作hbase大表迁移,造成大量rit

    1
    2
    3
    4
    5
    6
    # phoenix操作hbase大规模数据迁移,引发死锁,hbase-site.xml增加如下配置重启hbase region server服务
    #hbase-site.xml (
    <property>
    <name>hbase.regionserver.executor.openregion.threads</name>
    <value>100</value>
    </property>
  • region server graceful stop
    在关闭hbase region server的时候,为了不影响线上业务,尽量先执行hbase graceful_stop.sh 脚本进行优雅关闭(主要是关闭前进行节点上region 的迁移)

oozie

  • oozie调度频率限制问题

    默认情况下,oozie调度的最快频率是5分钟一次。可以把oozie.service.coord.check.maximum.frequency设置为false来屏蔽这个限制

  • stream exceeds limit报错

    1
    2
    3
    4
    5
    6
    7
    8
    #oozie调度任务偶发性耗时很长
    #查看日志有stream exceeds limit[2048]报错
    #修改oozie-site.xml 配置文件重启oozie server:

    <property>
    <name>oozie.servlet.CallbackServlet.max.data.len</name>
    <value>8192</value>
    </property>

sqoop

  • sqoop备份hive数据到mysql偶发报错

    hive2.3.3 与sqoop 1.4.7 lib中有jar包冲突, 移除hive/lib目录下的derbyclient-10.11.1.1.jar, derbynet-10.11.1.1.jar这两个包解决问题
    issue:https://issues.apache.org/jira/browse/HIVE-19836

presto

  • presto 配置几个规则注意

    1
    2
    3
    4
    5
    # config.properties 如果配置不合理,可能导致presto worker无法启动
    #resources.reserved-system-memory default = jvm*0.4 (system mem)
    # memory.heap-headroom-per-node default = jvm*0.3
    # query.max-memory-per-node < query.max-total-memory-per-node
    # memory.heap-headroom-per-node + query.max-memory-per-node < jvm
  • 关于cpu
    presto任务运行起来,简直是cpu收割机,尽量不要把presto和hadoop相关服务部署在同一个节点上。

  • presto 0.208的hive数据源访问坑很多,请绕行
  • presto 0.209及之后的版本需要 jdk8u_151+

zeppelin

  • dashboar无法查看notebook list

    zeppelin 0.8.1中不要创建名字为’/‘的notebook, 会导致控制台无法看到notebook list, 可以去zeppelin安装目录的notebook下找到对应notebook,删除后重启zeppelin服务

  • 关于interpreter的依赖jar

    对于创建interpreter的Dependencies配置,配置的artifact后,默认去公网下载,如果无外网,需要自己指定jar包绝对路径

  • jdbc interpreter

    目前zeppelin对所有支持标注jdbc的组件不再单独提供interpreter, 比如hive,presto,mysql等,需要自己创建interpreter并指定jdbc driver和连接地址即可。
    对于presto 0.180+,直接使用官网提供的presto jdbc jar包进行访问,会报参数检验错误,简单粗暴的解决方法:处理方法: 从github下载presto源代码,git checkout 0.2220切换到0.220 tag版本, 进入presto-jdbc/src/main/java/com/facebook/presto/jdbc文件夹,注释掉95行的validateConnectionProperties(properties),在请求时,不进行连接参数验证,编译一个新的presto-jdbc jar包即可。

tez

  • 配置文件相关

tez-site.xml中的tez.am.resource.memory.mb指定了tez application master的堆内存,如果过小可能造成任务异常退出

hive-site.xml中的hive.tez.container.size可以指定 tez task container的内存配置

参考: hive-on-tez调优

  • conflicting local resource报错问题

在hive2.3.3使用tez-0.8.5的时候,出现java.lang.IllegalStateException: There is conflicting local resource (xxx.jar) between dag local resource and vertex Reducer 2 local resource 类似的报错,排查看这些包都是放在hive的auxlib目录下,查看源码报错是在tez-api/src/main/java/org/apache/tez/dag/api/DAG.java这个文件,对比tez-0.8.5和tez-0.9.2的代码,发现社区已经优化了jar包文件对比的逻辑,如果文件的size一致就任务文件没有冲突。
所以,在使用tez-0.8.5的时候,可以修改这里的检测逻辑,采用tez-0.9.1的代码,进行tez-api模块的重新编译,替换线上的tez-api-0.8.5.jar包即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# tez-0.8.5-rc1 
# 695行 https://github.com/apache/tez/blob/release-0.8.5-rc1/tez-api/src/main/java/org/apache/tez/dag/api/DAG.java

// check for conflicts between dag level local resource and vertex level local resource
for (Vertex v : vertices.values()) {
for (Map.Entry<String, LocalResource> localResource : v.getTaskLocalFiles().entrySet()) {
String resourceName = localResource.getKey();
LocalResource resource = localResource.getValue();
if (commonTaskLocalFiles.containsKey(resourceName)
&& !commonTaskLocalFiles.get(resourceName).equals(resource)) { //这里的比较,可能同一个文件的两个拷贝,就有可能抛出异常
throw new IllegalStateException("There is conflicting local resource (" + resourceName
+ ") between dag local resource and vertex " + v.getName() + " local resource. "
+ "\nResource of dag : " + commonTaskLocalFiles.get(resourceName)
+ "\nResource of vertex: " + resource);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#tez-0.9.1-rc0
# 701行 https://github.com/apache/tez/blob/release-0.9.1-rc0/tez-api/src/main/java/org/apache/tez/dag/api/DAG.java

for (Vertex v : vertices.values()) {
for (Map.Entry<String, LocalResource> localResource : v
.getTaskLocalFiles().entrySet()) {
String resourceName = localResource.getKey();
LocalResource resource = localResource.getValue();
if (commonTaskLocalFiles.containsKey(resourceName)
&& !commonTaskLocalFiles.get(resourceName).equals(resource)) {
// Different for some reason. Compare size, and then eventually hash
try {

LocalResource commonLr = commonTaskLocalFiles.get(resourceName);
if (resource.getSize() != commonLr.getSize()) { //这里额外增加文件大小判断,同一个文件的两份拷贝不会抛出异常
throw new IllegalStateException(
"There is conflicting local resource (size mismatch) (" +
resourceName
+ ") between dag local resource and vertex " +
v.getName() + " local resource. "
+ "\nResource of dag : " +
commonTaskLocalFiles.get(resourceName)
+ "\nResource of vertex: " + resource);
}

tips:如果hive on tez 情况下,hive auxlib文件夹放了过多的jar包,可能会造成hive cli启动变慢,因为需要将auxlib下的jar包上传到hdfs的tez session文件夹下