phpHiveAdmin 软件开发和知识整理 (hive 读取后台log)
2013-04-15 14:44 java20130722 阅读(370) 评论(0) 编辑 收藏 举报访问Hive接口有thrift,这没有太多可说的,只要调用封装好的方法就行了。之前因为Socket的阻塞问题,经常会发生Hive接口读取超时,修改一下Thrift里面的TSocket.php就好了。修改方法参看之前的php开发Hive web查询,跟网上的其他相关文章还是略有区别。
数据库的管理方面主要就是获取网页变量,然后拼sql字符串,这好像也没啥可讲的。多看Hive手册就会了。
核心内容是查询部分,这个是比较有趣的地方,最早的一版查询是完全用thrift完成的,查询特别慢不说,关键是没有进度返回,而且如果中间关闭窗口就彻底找不到任务了。当时十分羡慕淘宝的Hive界面,有map/reduce进度条。于是自己调了两天,写了一个获取map/reduce进度的方法,虽然没有进度条,但是可以读取到Hive执行的map/reduce进度,并实时返回。其核心思路是既然hive命令行可以将mr进度打印到控制台上的stdout和stderr,那就写个程序读命令行执行的stdout和stderr就好了。但是要实时输出到网页的话,就需要边读边写,这对php来说就比较难了。对于php程序员来说,绝大多数是开发网页的,用到线程和进程管理的非常少,极少。根据php针对网页的特点。如果不用ajax,php本身无法对进程进行异步处理。但是系统执行是在后端的,跟网页无关,所以其实这是一个php在操作系统方面进行异步执行的问题。pcntl是子进程管理,比较方便,但是需要在php编译的时候enable,我不想给自己找麻烦,特别是不想给其他用户造成困难,所以最后选择了proc_open来新开一个进程完成异步的处理。至于为什么没有选择Java开发,或者python开发,也是考虑其实相比于php,java和python在网页方面的开发还是偏小众,配置LNMP可能会更大众化,或许可以让大家上手大数据更轻松一些。但是也不排除将来会用java或者python再写一版,反正写完交给别人自己查数管集群,我也没事干,闲着也是闲着。
所以核心就在下面。
一个hive查询通过页面发送给命令行执行,网页会在服务器上通过proc_open创建一个php进程,然后读取Hive命令行执行返回的stdout和stderr,将执行过程的输出写入到一个临时文件。然后前端的页面会读取这个文件,将内容倒排后返回给网页,这样就完成了map/reduce的实时读取。说起来简单,写起来还是比较难的。中间还要涉及到Linux基本环境的配置,对HADOOP,HIVE,JAVA环境变量的输出。通常php工作在nobody或者www这样的用户下面,这种用户的默认shell是/sbin/nologin,似乎这类用户不会获得任何环境变量。所以必须在发送Hive命令行查询之前,将环境变量发给操作系统。整个这一套新开进程加发现环境变量问题等等,调通用了整整两天。
- public function NonBlockingRun($pCmd,$pTimestamp,$pFilename,$pType,&$pCode)
- {
- global $env;
- $descriptorspec = array(
- 0 => array("pipe", "r"),
- 1 => array("pipe", "w"),
- 2 => array("pipe", "w")
- );
- $pipes= array();
- $process = proc_open($pCmd, $descriptorspec, $pipes);
- $output= "";
- if (!is_resource($process))
- {
- return false;
- }
- fclose($pipes[0]);
- stream_set_blocking($pipes[1],0);
- stream_set_blocking($pipes[2],0);
- $todo= array($pipes[1],$pipes[2]);
- $fp = fopen($pFilename,"w");
- #fwrite($fp,$pTimestamp."\n\n");
- while( true )
- {
- $read= array();
- #if( !feof($pipes[1]) ) $read[]= $pipes[1];
- if( !feof($pipes[$pType]) ) $read[]= $pipes[$pType];// get system stderr on real time
- if (!$read)
- {
- break;
- }
- $ready= stream_select($read, $write=NULL, $ex= NULL, 2);
- if ($ready === false)
- {
- break; #should never happen - something died
- }
- foreach ($read as $r)
- {
- $s= fread($r,128);
- $output .= $s;
- fwrite($fp,$s);
- }
- }
- fclose($fp);
- fclose($pipes[1]);
- fclose($pipes[2]);
- $pCode= proc_close($process);
- return $output;
- }
这段就是主要用来读取Hive命令行输出的代码,这样做的好处是,所有Hive发行版通吃,只要他能够在命令行输出内容,就能用phpHiveAdmin。什么Apache版,Cloudera版,都能用。不方便的地方是,必须在运行phpHiveAdmin的机器上部署一个Hive和Hadoop(无需运行Hadoop,只要能访问集群即可),phpHiveAdmin依赖于Hive可执行文件。但是并没有因此抛弃thrift接口,thrift用来获取库名表名,执行Hive管理什么alter,drop,create,insert命令还是非常好用的。
回顾一下现在的工作,也是个挺神奇的事情,当吐个槽吧,最早刚进公司并不是以数据部门的名额被招进来的,只是个php web程序员,做在线部门的开发。那时候的那个领导姓张,上班第一天就让我做项目,我用了大概两周的时间,搭建了一整套基于scribe和awk的日志采集和分析系统,除了生成报表,基本我一人全包了。awk脚本都写好了,然后那家伙跟我说,你水平太差,你还是走吧。上班两周做完一项目,然后要开掉我。当时震惊的无以复加,就去找人事说了一下这个情况,人事帮我转到了数据部门。正好数据部门在搞hadoop,阴差阳错。当时觉得hadoop安装太费劲,就在老赵调研的基础上写了个脚本。然后觉得Hive操作不方便,就写了phpHiveAdmin。在童小军的帮助下,phpHiveAdmin在2012年1月29日开源到github;EasyHadoop第一版安装脚本在2012年1月31日开源到github。
在这里要特别感谢公司里的3个人,首先是在线部门姓张的领导,如果不是因为你想让我干完项目就开掉我,我是不会到数据部门接触Hadoop的,不接触Hadoop就写不了EHM和PHA,写不了EHM和PHA我的博客就没啥可写的。所以,尽管我非常厌恶你,但是还是需要感谢一下,因为有你的逆天存在,我才有机会写出这篇博客。真心感谢,不是吐槽高级黑。虽然我也很想趁你走夜路的时候拍板砖,不为我,为那些被你排挤走的优秀的同事。所以骂归骂,该感谢还是得感谢。
其次感谢的是数据部门的前任领导童小军,也是现在EasyHadoop社区扛大旗的人,基于他的鼓励和工作协调下,我才能够有时间开发和维护这两个项目。也正是基于他的努力,才有了一个开源,开放的社区。
还有前任同事赵修湘,教会了我很多Hadoop生态圈的相关知识,盼望我们再次共事的那一天。
十分感谢公司数据组的每一位同事,有你们帮我分担MR任务,才有EHM的PHA的诞生,你们是最棒的。