使用Hive的HWI接口,可以通过在Web页面上提交HQL查询操作,并浏览查询结果数据。默认情况下,HWI只支持浏览结果数据,不能够下 载查询结果文件(当然,HWI可能也是考虑通过Web下载大量的结果数据,对服务器造成压力,或者处于安全方面的考虑)。我们对HWI进行了简单的改造, 改造内容主要是增加了一个内置的文件服务器,可以通过页面进行查询,然后下载结果文件。
HWI安装配置
首先,要保证Hadoop集群正常运行,Hive能够正常使用。
先要安装Ant,如下所示:
2 |
tar xvzf apache-ant-1.9.4-bin. tar .gz
|
3 |
ln -s /usr/ local /apache-ant-1.9.4-bin /usr/ local /ant
|
修改Hive的环境配置文件hive-env.sh,增加如下配置内容:
1 |
export ANT_LIB=/usr/ local /ant
|
将如下JAR文件拷贝到${HIVE_HOME}/lib目录下面:
2 |
jasper-compiler-5.5.23.jar |
3 |
jasper-runtime-5.5.23.jar |
5 |
// 替换默认的servlet-api-2.5-20081211.jar,我使用的是apache-tomcat-7.0.53/lib下面的servlet-api.jar文件 |
另外,由于Hive 0.12.0版本的HWI的问题,需要将你的${JAVA_HOME}/lib/tools.jar文件也加入到${HIVE_HOME}/lib目录下。这个算是一个Bug吧,大概要到Hive 0.13.0版本能够解决。
接下来,需要在${HIVE_HOME}/conf/hive-site.xml配置文件中,加入如下配置内容:
03 |
< name >hive.hwi.listen.host</ name >
|
04 |
< value >0.0.0.0</ value >
|
05 |
< description >This is the host address the Hive Web Interface will listen on.</ description >
|
08 |
< name >hive.hwi.listen.port</ name >
|
10 |
< description >This is the port the Hive Web Interface will listen on.</ description >
|
13 |
< name >hive.hwi.war.file</ name >
|
14 |
< value >/lib/hwi.war</ value >
|
15 |
< description >This is the WAR file with the jsp content for Hive Web Interface.</ description >
|
其中,属性hive.hwi.war.file对应的hwi.war文件,我们会在后面改造之后重新打包为该文件,并拷贝到${HIVE_HOME}/lib目录下面。
HWI改造
默认使用HWI是没有查询结果文件下载功能的,可以增加一个文件服务器,用来存放并提供下载查询结果文件。这里,我发现HWI虽然也提供一个Web 容器,但是由于封装的太深,所以放弃修改内部源码,而是直接通过我熟悉的方式,使用Jetty实现了一个文件服务,需要用到下面的一些JAR文件:
02 |
jetty-continuation-8.1.0.RC5.jar |
03 |
jetty-io-8.1.0.RC5.jar |
04 |
jetty-server-8.1.0.RC5.jar |
05 |
jetty-util-8.1.0.RC5.jar |
06 |
jetty-xml-8.1.0.RC5.jar |
07 |
jetty-http-8.1.0.RC5.jar |
08 |
jetty-security-8.1.0.RC5.jar |
09 |
jetty-servlet-8.1.0.RC5.jar |
10 |
jetty-webapp-8.1.0.RC5.jar |
首先,定义一个服务器接口,用来控制文件服务器的启停操作等,如下所示:
01 |
package org.shirdrn.hadoop.hive.jetty;
|
03 |
public interface JettyServer {
|
07 |
/** Start this server. */
|
10 |
/** Stop this server. */
|
13 |
/** Wait for this server to exit. */
|
14 |
void join() throws InterruptedException;
|
然后,实现一个文件服务器,代码如下所示:
01 |
package org.shirdrn.hadoop.hive.jetty;
|
03 |
import java.util.HashMap;
|
04 |
import java.util.Iterator;
|
06 |
import java.util.Map.Entry;
|
08 |
import org.apache.commons.logging.Log;
|
09 |
import org.apache.commons.logging.LogFactory;
|
10 |
import org.eclipse.jetty.server.Server;
|
11 |
import org.eclipse.jetty.server.handler.DefaultHandler;
|
12 |
import org.eclipse.jetty.server.handler.HandlerList;
|
13 |
import org.eclipse.jetty.server.handler.ResourceHandler;
|
14 |
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
17 |
* Jetty file server for handling hvie query result file downloading. |
21 |
public class JettyFileServer implements JettyServer {
|
23 |
private static final Log LOG = LogFactory.getLog(JettyFileServer. class );
|
24 |
private final Server server;
|
25 |
private final int port = 9722 ;
|
27 |
static Map<String, String> users = new HashMap<String, String>();
|
28 |
static Map<String, String> resourceBases = new HashMap<String, String>();
|
30 |
users.put( "user" , "user" );
|
31 |
resourceBases.put( "user" , "/download" );
|
34 |
public JettyFileServer() {
|
35 |
server = new Server(port);
|
36 |
SelectChannelConnector connector = new SelectChannelConnector();
|
37 |
server.addConnector(connector);
|
39 |
HandlerList handlers = new HandlerList();
|
40 |
createFileServerContexts(handlers);
|
42 |
handlers.addHandler( new DefaultHandler());
|
44 |
server.setHandler(handlers);
|
47 |
private void createFileServerContexts(HandlerList handlers) {
|
48 |
Iterator<Entry<String, String>> iter = users.entrySet().iterator();
|
49 |
while (iter.hasNext()) {
|
50 |
Entry<String, String> entry = iter.next();
|
51 |
String user = entry.getKey();
|
52 |
String fileBase = resourceBases.get(user);
|
53 |
ResourceHandler resourceHandler = createResourceHandler(user, fileBase);
|
54 |
handlers.addHandler(resourceHandler);
|
58 |
private ResourceHandler createResourceHandler(String user, String fileBase) {
|
59 |
ResourceHandler resourceHandler = new ResourceHandler();
|
60 |
resourceHandler.setDirectoriesListed( true );
|
61 |
resourceHandler.setWelcomeFiles( new String[]{ "index.html" });
|
62 |
resourceHandler.setResourceBase(fileBase);
|
63 |
return resourceHandler;
|
67 |
public int getPort() {
|
75 |
} catch (InterruptedException e) {
|
76 |
} catch (Exception e) {
|
77 |
throw new RuntimeException( "Fail to start Jetty file server!" , e);
|
85 |
} catch (Exception e) {
|
86 |
throw new RuntimeException( "Fail to stop Jetty file server!" , e);
|
91 |
public void join() throws InterruptedException {
|
这里,为了简化,我没有使用配置的方式,配置文件服务器的resource base目录,直接写死路径在代码里面,默认是/download目录,主要的是,这个目录需要设置一下权限,可以允许任何人写,但是不能覆盖别人已经写的文件(执行查询生成的结果文件):
- 增加一个ServletContextListener
主要用来启动文件服务器,实现类FileServerContextListener的代码如下所示:
01 |
package org.shirdrn.hadoop.hive.jetty;
|
03 |
import javax.servlet.ServletContextEvent;
|
05 |
import org.apache.commons.logging.Log;
|
06 |
import org.apache.commons.logging.LogFactory;
|
08 |
public class FileServerContextListener implements javax.servlet.ServletContextListener {
|
10 |
protected static final Log l4j = LogFactory.getLog(FileServerContextListener. class
|
12 |
private JettyServer fileServer;
|
14 |
public void contextInitialized(ServletContextEvent sce) {
|
16 |
l4j.info( "Start Jetty file server..." );
|
17 |
JettyServer server = new JettyFileServer();
|
19 |
l4j.info( "Jetty file server started!" );
|
22 |
public void contextDestroyed(ServletContextEvent sce) {
|
25 |
l4j.info( "Jetty file server stopped!" );
|
然后,需要在web.xml文件中增加如下配置:
2 |
< listener-class >org.shirdrn.hadoop.hive.jetty.FileServerContextListener</ listener-class >
|
因为我们可能需要将HWI暴露给组织内部的其他项目团队使用,只允许他们查询,就应该限制Hive的DDL、DML操作,不运行他们建库建表、
这里,需要修改页面session_manage.jsp,修改后的内容,如下所示:
001 |
<%@page import="org.apache.hadoop.hive.hwi.*" %> |
002 |
<%@page import="java.util.Arrays" %> |
003 |
<%@page import="java.util.List" %> |
004 |
<%@page errorPage="error_page.jsp" %> |
005 |
<% HWISessionManager hs = (HWISessionManager) application.getAttribute("hs");; %> |
007 |
<% HWIAuth auth = (HWIAuth) session.getAttribute("auth"); %> |
008 |
<% if (auth==null) { %> |
009 |
< jsp:forward page = "/authorize.jsp" />
|
011 |
<% String sessionName=request.getParameter("sessionName"); %> |
012 |
<% HWISessionItem sess = hs.findSessionItemByName(auth,sessionName); %> |
013 |
<% String message=null; %> |
015 |
String randomFile = String.valueOf(System.currentTimeMillis()) + ".txt"; // 生成随机文件名称
|
016 |
String errorFile=request.getParameter("errorFile");
|
017 |
String resultFile=request.getParameter("resultFile");
|
018 |
resultFile = "/user/download/" + resultFile; // 结果文件存储的路径
|
019 |
String query = request.getParameter("query");
|
020 |
String silent = request.getParameter("silent");
|
021 |
String start = request.getParameter("start");
|
023 |
// 简单的HQL操作过滤,限制DDL、DML操作
|
024 |
String[] stoppedKeywords = new String[] {
|
025 |
"INSERT", "DELETE", "TRUNCATE",
|
026 |
"CREATE", "DROP", "ALTER",
|
027 |
"GRANT", "REVOKE", "LOAD"
|
029 |
List< String > list = Arrays.asList(stoppedKeywords);
|
031 |
String q = query.toUpperCase();
|
032 |
String[] a = q.split("\\s+");
|
034 |
if(list.contains(w)) { // 如果包含上述关键词,直接抛出异常,限制执行操作
|
035 |
String err = "Permission denied! Excludes operations: " + list;
|
036 |
throw new HWIException(err);
|
042 |
if (request.getParameter("start")!=null ){
|
043 |
if ( sess.getStatus()==HWISessionItem.WebSessionItemStatus.READY){
|
044 |
sess.setErrorFile(errorFile);
|
045 |
sess.setResultFile(resultFile);
|
048 |
for (String q : query.split(";") ){
|
051 |
if (query.length()==0){
|
052 |
message="You did not specify a query";
|
055 |
if (silent.equalsIgnoreCase("YES") )
|
056 |
sess.setSSIsSilent(true);
|
058 |
sess.setSSIsSilent(false);
|
060 |
message="Changes accepted.";
|
061 |
if (start.equalsIgnoreCase("YES") ){
|
063 |
message="Session is set to start.";
|
071 |
< title >Manage Session <%=sessionName%></ title >
|
072 |
< link href = "css/bootstrap.min.css" rel = "stylesheet" >
|
074 |
< body style = "padding-top: 60px;" >
|
075 |
< jsp:include page = "/navbar.jsp" ></ jsp:include >
|
076 |
< div class = "container" >
|
079 |
< jsp:include page = "/left_navigation.jsp" />
|
084 |
<%=sessionName%></ h2 >
|
086 |
<% if (message != null) { %>
|
087 |
< div class = "alert alert-info" ><%=message %></ div >
|
090 |
<% if (sess.getStatus()==HWISessionItem.WebSessionItemStatus.QUERY_RUNNING) { %>
|
091 |
< div class = "alert alert-warning" >Session is in QUERY_RUNNING
|
092 |
state. Changes are not possible!</ div >
|
095 |
<% if (sess.getStatus()==HWISessionItem.WebSessionItemStatus.QUERY_RUNNING){ %>
|
097 |
View JobTracker: < a href="<%= sess.getJobTrackerURI() %>">View Job</ a >< br >
|
098 |
Kill Command: <%= sess.getKillCommand() %>
|
099 |
Session Kill: < a href="/hwi/session_kill.jsp?sessionName=<%=sessionName%>"><%=sessionName%></ a >< br >
|
103 |
< div class = "btn-group" >
|
104 |
< a class = "btn" href="/hwi/session_history.jsp?sessionName=<%=sessionName%>">< i class = "icon-book" ></ i > History</ a >
|
105 |
< a class = "btn" href="/hwi/session_diagnostics.jsp?sessionName=<%=sessionName%>">< i class = "icon-cog" ></ i > Diagnostics</ a >
|
106 |
< a class = "btn" href="/hwi/session_remove.jsp?sessionName=<%=sessionName%>">< i class = "icon-remove" ></ i > Remove</ a >
|
107 |
< a class = "btn" href="/hwi/session_result.jsp?sessionName=<%=sessionName%>">< i class = " icon-download-alt" ></ i > Result Bucket</ a >
|
110 |
< form action = "session_manage.jsp" class = "form-horizontal" >
|
111 |
< input type = "hidden" name = "sessionName" value="<%=sessionName %>">
|
114 |
< legend >Session Details </ legend >
|
115 |
< div class = "control-group" >
|
116 |
< label class = "control-label" for = "fldresfile" >Result File</ label >
|
117 |
< div class = "controls" >
|
118 |
< input id = "fldresfile" type = "text" name = "resultFile"
|
119 |
readonly value="<%=randomFile%>">
|
120 |
<% if (sess.getResultFile()!=null) { %>
|
121 |
< a href="/hwi/view_file.jsp?sessionName=<%=sessionName%>">View File</ a >
|
123 |
String[] a = sess.getResultFile().split("/");
|
124 |
String file = a[a.length - 1];
|
132 |
< div class = "control-group" >
|
133 |
< label class = "control-label" for = "flderrfile" >Error File</ label >
|
134 |
< div class = "controls" >
|
135 |
< input id = "flderrfile" type = "text" name = "errorFile"
|
137 |
if (sess.getErrorFile()==null) { out.print(""); } else { out.print(sess.getErrorFile()); }
|
142 |
< div class = "control-group" >
|
143 |
< label class = "control-label" for = "fldquery" >Query</ label >
|
144 |
< div class = "controls" >
|
145 |
< textarea id = "fldquery" name = "query" rows = "8" cols = "70" >
|
147 |
if (sess.getQueries()==null) {
|
150 |
for (String qu: sess.getQueries() ) {
|
151 |
out.print(qu); out.print(" ; ");
|
160 |
< div class = "control-group" >
|
161 |
< label class = "control-label" for = "fldsilent" >Silent Mode</ label >
|
162 |
< div class = "controls" >
|
163 |
< select id = "fldsilent" name = "silent" >
|
165 |
<% if (sess.getSSIsSilent()==true) { out.print("SELECTED=\"TRUE\""); } %>>YES</ option >
|
167 |
<% if (sess.getSSIsSilent()==false) { out.print("SELECTED=\"TRUE\""); } %>>NO</ option >
|
172 |
< div class = "control-group" >
|
173 |
< label class = "control-label" for = "fldstart" >Start Query</ label >
|
174 |
< div class = "controls" >
|
175 |
< select id = "fldstart" name = "start" >
|
176 |
< option value = "YES" SELECTED = "TRUE" >YES</ option >
|
177 |
< option value = "NO" >NO</ option >
|
184 |
< h3 >Query Return Codes</ h3 >
|
186 |
<% for (int i=0; i< sess.getQueryRet ().size();++i ){ %>
|
189 |
<%=sess.getQueryRet().get(i)%>< br >
|
193 |
<% if (sess.getStatus()!=HWISessionItem.WebSessionItemStatus.QUERY_RUNNING) { %>
|
194 |
< div class = "form-actions" >
|
195 |
< button type = "submit" class = "btn btn-primary" >Submit</ button >
|
上面注释的地方,说明了修改的内容,可以查看。
HWI重新构建
我们只需要将我们自己实现的代码部分,打包到WAR文件里面就可以,因为默认的HWI的Java实现部分,可以在Hive的软件包中找到,可以查 看${HIVE_HOME}/lib/hive-hwi-0.12.0.jar。上面我们改造过程中实现了一个Jetty文件服务器,编译完成后,需要删 除默认目录${HWI_HOME}\target\WEB-INF\classes下面,不是我们改造后增加的类的类文件,然后就可以执行如下命令构建:
然后,将生成的hwi文件,拷贝到部署Hive的对应目录${HIVE_HOME}/lib/下面即可,启动HWI服务:
1 |
hive --service hwi >> /tmp/hwi/hwi.log & |
然后,就可以通过Web页面访问。
HWI使用
访问页面,例如我的是http://10.10.2.245:9999/hwi,然后,可以看到HWI首页,执行如下操作进行查询:
- 点击“Authorize”,填写“User”和“Groups”的内容,例如都是hadoop,然后点击提交按钮“Submit”;
- 点击“Create Session”,填写“Session name”,例如MYSESSION[hadoop],然后点击提交按钮“Submit”;
- 这时,进入到Manage Session MYSESSION[hadoop]页面,可以在“Query”中输入HQL查询语句,“Start Query”选择“YES”,然后击提交按钮“Submit”;
- 可以通过“View File”和“Result Bucket”查看结果内容;
- 可以通过我们改造后的“Download File”链接,进行查询结果文件的下载。
参考链接
From: http://shiyanjun.cn/archives/885.html
相关推荐
Hive-0.12.0是Hive的一个早期版本,虽然现在已经有了更多更新的版本,但这个版本在当时仍具有重要的意义,尤其对于初次接触Hive或者需要使用特定功能的用户来说。 Hive的核心特性包括以下几个方面: 1. **数据存储...
hive-0.12.0.part1.rar hive-0.12.0.part1.rar
已经测试ok的hive-hwi-0.12.0-cdh5.0.0.war文件,直接放到hive/lib下可用
hive-0.12.0.part2.rar
### Hive-1.2.1-hwi配置详解 #### 一、概述 Hive是一款基于Hadoop的数据仓库工具,它可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能,使得Hadoop能够更好地处理大数据。在Hive 1.2.1版本中,引入...
含两个文件hive-jdbc-3.1.2-standalone.jar和apache-hive-3.1.2-bin.tar.gz 含两个文件hive-jdbc-3.1.2-standalone.jar和apache-hive-3.1.2-bin.tar.gz 含两个文件hive-jdbc-3.1.2-standalone.jar和apache-hive-...
1. `hive-jdbc-1.1.0-cdh5.12.1-standalone.jar`:这是一个独立的jar包,包含了所有必要的依赖,可以直接在没有其他CDH库的情况下运行。这意味着如果你的客户端环境中无法或不便解决所有依赖问题,你可以选择使用这...
apache-hive-2.1.1-bin.tar apache-hive-2.1.1-bin.tar apache-hive-2.1.1-bin.tarapache-hive-2.1.1-bin.tar apache-hive-2.1.1-bin.tar apache-hive-2.1.1-bin.tarapache-hive-2.1.1-bin.tar apache-hive-2.1.1-...
【标题】"Hive-HWI:Hive Web Interface(网页版接口)" 【描述】"在深入探讨Hive-HWI之前,我们先了解Hive的基本概念。Hive是由Facebook开发的一种基于Hadoop的数据仓库工具,它允许用户使用SQL-like语言(HQL,...
3. 配置Hive-site.xml:根据实际Hadoop集群环境配置Hive的相关参数,如metastore的URI、HDFS的路径等。 4. 初始化Metastore:运行Hive的schematool工具,初始化元数据存储。 5. 启动Hive:使用hive命令启动Hive CLI...
02、hive-exec-2.1.1-cdh6.3.1.jar 03、hive-jdbc-2.1.1-cdh6.3.1.jar 04、hive-jdbc-2.1.1-cdh6.3.1-standalone.jar 05、hive-metastore-2.1.1-cdh6.3.1.jar 06、hive-service-2.1.1-cdh6.3.1.jar 07、libfb303-...
在Dbeaver中,为了连接到Hive服务器,用户需要配置Hive的JDBC驱动,而**hive-jdbc-uber-2.6.5.0-292.jar**就是这个配置过程中不可或缺的部分。用户需要将此驱动添加到Dbeaver的驱动定义中,指定正确的URL、用户名和...
安装Yanagishima时,需要将"Hive-jdbc-uber-3.1.2.jar"配置到其类路径中,以便与Hive服务通信。同时,还需要配置Kerberos认证的相关参数,如principal和keytab文件的位置,以确保Yanagishima能够在安全模式下正常...
hive-exec-2.1.1 是 Apache Hive 的一部分,特别是与 Hive 的执行引擎相关的组件。Apache Hive 是一个构建在 Hadoop 之上的数据仓库基础设施,它允许用户以 SQL(结构化查询语言)的形式查询和管理大型数据集。Hive ...
spark下安装hive标准配置文档。Ubuntu安装hive,并配置mysql作为元数据库时候需要的标准hive-site.xml配置文件,可以根据这个文件联系我的博文内容就行修改,避免入坑。实现快捷启动hive。
本文将详细讲解如何使用"Dbeaver链接Hive驱动包:hive-jdbc-uber-2.6.5.0-292.jar",并探讨其在实际工作中的应用。 一、Hive JDBC驱动简介 Hive JDBC(Java Database Connectivity)驱动是Hive与Java应用程序之间...
hive-jdbc-2.1.1-cdh6.2.0(ieda等jdbc链接hive2.1.1);cdh6.2.0安装的hive2.1.1
"hive-jdbc-jar-多版本.zip"是一个压缩包,包含了不同版本的Hive JDBC Uber Jars,覆盖了从1.5到1.8的多个Hive版本,适应不同的项目需求。 首先,我们要理解Uber JAR的概念。Uber JAR(也称为Shaded JAR)是一个...
3. `conf/`:默认的配置文件,如`hive-default.xml`和`hive-site.xml`,用户可以在此修改Hive的行为。 4. `scripts/`:包含Hive的一些初始化和管理脚本。 5. `metastore/`:元数据存储相关的库和脚本,Hive使用元...
在给定的标题“hive-jdbc-1.2.1-standalone”中,"standalone"表示这是一个独立的版本,包含了运行Hive JDBC所需的所有依赖,无需额外安装或配置其他Hive或Hadoop组件。 描述中提到的“hadoop-common-2.6.4”是...