hadoop和hive结合使用总结(关于一个稳定性的问题)

最近在外网试运行了一个月以来,hive在hadoop平台中的一个主要问题是:

经常报此异常:

org.apache.hadoop.ipc.Server: IPC Server handler 495 on 8020 caught: java.nio.channels.ClosedChannelException

导致任务执行失败(每次任务失败,关闭的连接都是hive连接到hadoop的master机器上的hdfs端口,后来也观察过日志,发现namenode与datanode交互时,也会出现关闭连接的情况,但这不影响任务的执行)


之前有几篇blog都是于此有关联的,大家可以自己去看看。

目前我们这个应用每天的计算规模在2亿多的数据量,而且必须保证数据计算的正确性和可用性。

hive运行情况如下:

因为刚开始应用不多,hive和hadoop的NameNode在一台机器上面,另外调度器也没有去限制最大运行JOB个数,

job采用的是hive的并行模式(设置参数hive.exec.parallel),并且多脚本也是可以并行运行(也就是多个hive进程,目前采用的命令模式运行)。

当采用这种方式后,在多个job同时提交,并且hive与hadoop交互比较紧密的时候,就会出现以上这种异常。


通过官方的issue(https://issues.apache.org/jira/browse/MAPREDUCE-2450)来看,他也只是初步的分析了问题的原因,至于解决方案各有不同。

通过3个多礼拜的不断地的尝试和测试(在此过程中修过了3遍hive脚本,尝试了过很多参数的修改,各种调度器的使用,操作系统相关修改),大致摸索了点东西出来。

原来在hadoop的RPC机制中有个小问题,该问题与以下几个方面有关:

1、一定要同步好集群里所以节点的时间

2、参数ipc.server.read.threadpool.size设置,该参数配置在core-site.xml(该参数不在官方的文档里体现出来),简单介绍下该参数的作用:

      默认情况下取值为1,也就是1个读线程操作,为了提高NameNode的读能力,可以将该参数设置更大。

      但是当该参数设置更大的时候,将引起一个问题(关于hadoop里RPC的原理,这里不详细描述):

      就是当一个连接要关闭的时候, 之前的请求处理来不及返回。这样就会在请求返回时抛出该连接已被关闭的异常,这种异常将影响到任务的正常运行(之前hive出现的相关问题),经过仔细的排查,也是由于这个原因导致(也有其他因素,跟ipc.ping.interval这个参数的设置也有关系)

 

解决方式:

第一:就是不要轻易去设置ipc.server.read.threadpool.size的值(但是一般随着集群的规模越来越大,还是需要设置的)

第二:为了提高hadoop的读能力,我修改RPC交互方式

第三:研究hive的调用机制,查找是否有什么可疑之处

第四:修改Client类里,捕获IOException异常,再重新创建一个连接

第五:在Server类里用handler类来关闭这个连接,而不是在读的时候进行关闭


以上几种方式,除了第二点外,其他都是要调整hadoop里的东东。


在这里我选择了第二种方式,处理如下:

我稍微在Server.java这个类做了点变动,代码如下:

publicvoid run() {

       LOG.info("Starting SocketReader");

       synchronized (this) {

          while (running) {

            SelectionKey key =null;

            try {

              int cons=readSelector.select();

              if (LOG.isDebugEnabled())

                  LOG.debug(getName()+" readSelector="+cons);

              while (adding) {

                this.wait(1000);

              }              

             this.wait(100);//读取时再暂停100毫秒 会出现之前的请求还没返回,连接被关闭的情况

              Iterator<SelectionKey> iter =readSelector.selectedKeys().iterator();

              while (iter.hasNext()) {

                key = iter.next();

                if (LOG.isDebugEnabled())

                    LOG.debug("Iterator "+key);

                iter.remove();

                if (key.isValid()) {

                  if (key.isReadable()) {

                  if (LOG.isDebugEnabled())

                      LOG.debug("Key is readable---------------" +key.attachment());

                     doRead(key);

                  }

                }

                key =null;

              }

            } catch (InterruptedException e) {

              if (running) {                      // unexpected -- log it

                LOG.info(getName() + " caught: " +

                         StringUtils.stringifyException(e));

              }

            } catch (IOException ex) {

              LOG.error("Error in Reader", ex);

            }

          }

        }

      }

 

注意以上代码红色字体部分,注意:有部分DEBUG日志,是我自己加的,大家不必介意。



目前我测试过第二种方式,没有出现过问题,不过通过两天的测试效果来看,感觉可以把暂停的时间还设置小点,(后面打算测试下50毫秒的情况)

测试下来发现,虽然不会出现sever端读到-1后主动关闭连接了,但是会出现server端读异常。

 

关于第一种方式,是系统默认的,目前我还没有尝试过(刚开始上线的时候就设置为5),但也会对这种方式进行测试,看看是否还报连接关闭的异常。

第三种方式也在进行中,主要是研究下hive为什么在没有接收到上一个请求的响应信息,就发出了一个中断连接的指令。


测试三天发现:设置100毫秒将很影响job的运行速度。现在已经改到50毫秒进行测试并且同步进行不设置读线程数的测试工作。

目前第一种方式也不行,而且报连接关闭异常更频繁。

第四种和第五种方式初步考虑后,感觉比较复杂,所以不采用此方式。

 

 

在正常运行了两天后,又再次出现了NIO的异常,所以同步时间后和修改相关参数还是不够稳定。 

再次进行了三天的测试,发现最终的原因(在没修改任何源码的情况下)是:

服务器端收到count值为-1,所以服务器端会关闭这个连接。但客户端这时候会wait等待1分钟(默认设置值),在等待的过程中已经抛出了写异常(因为服务器端关闭了这个连接导致,也就抛出了java.nio.channels.ClosedChannelException),所以导致最终这个hive这个脚本任务终止。详细查看博客《Client与Server交互的错误信息》。

服务器端关闭连接的情况如下:

1、Listener当连接超时会主动关闭,但是关闭的原因是抛出OutOfMemoryError异常,会有以下操作:

       关闭当前的连接closeCurrentConnection,强制清理超时连接cleanupConnections(true)

2、Responder类当一个Call超时时也会清理连接(默认机制是上次返回response时间+PURGE_INTERVAL,大致是15分钟)

3、在读操作(doRead)的时候,当count<0时,就主动关闭连接

4、在写操作(doAsyncWrite)的时候,如果出现异常也将关闭连接

5、在读操作时会有验证操作,如果验证失败也将主动关闭连接

6、在读操作时有sasl处理,如果验证失败也将主动关闭连接

 

客户端的关闭连接情况如下:

1、创建一个连接时出现了Throwable异常,将主动关闭连接

2、在读的时候,如果waitForWork返回false的话,将主动关闭连接

在这里就有个问题就是当客户端在写之前,就无法知道知道当前连接是否被关闭。

 

关注新动向博客《         NIO异常新动向2         
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值