Ubuntu 22.04 安装部署 Apache Lens 指南

在 Ubuntu 22.04 上从零安装部署 Apache Lens 2.2.0-beta 的完整实录,涵盖依赖准备、发行包校验、Hadoop/Hive 运行依赖构造、服务端启动排障、源码编译、堆内存设置与卸载方式。

Apache LensLensApache安装部署Ubuntu 22.04Hadoop2026/10/15

Ubuntu 22.04 安装部署 Apache Lens 指南

一、部署方案与版本选择

Apache Lens 的最后一个版本是 2.2.0-beta-incubating(2015 年 7 月发布,项目已于 2020 年 8 月退役、2021 年 4 月进入 Attic),部署路线有两条:使用官方二进制发行包直接运行,或用源码包经 Maven 构建后运行。两条路线本文都完整实测通过,建议优先采用二进制路线——它绕开了构建环节的依赖陷阱;源码路线则作为需要定制或审计场景的补充,本文记录了其完整的依赖处理方法。

无论哪条路线,都要先理解 Lens 的部署特殊性:服务端 war 包内只含 Lens 自身与 Web 框架依赖(实测 war 内共 80 个 jar),刻意不捆绑 Hive 与 Hadoop 的 jar,启动脚本要求通过 HADOOP_HOME 与 HIVE_HOME 两个环境变量提供这两套运行依赖。因此"安装 Lens"实际由三部分组成:Lens 发行包本身、一个 Hadoop 发行目录、一个 Hive 依赖目录。更关键的是版本匹配:Lens 2.2.0-beta 源码 POM 锁定 Hive 版本为 0.13.3-inm(InMobi 维护的 0.13.3 fork)、Hadoop 版本 2.4.0,若直接使用 Apache 官方 Hive 0.13.1 的 jar,服务启动会因类不兼容立即崩溃,实测报 java.lang.NoSuchFieldError: HIVE_SESSION_IMPL_CLASSNAME。本文的 Hive 依赖目录构造方法正是针对这一问题的解法。

版本组合的实测结论:操作系统 Ubuntu 22.04,Java 采用 OpenJDK 8(Lens 按 Java 7/8 时代构建,README 明确标注更高版本 JDK 构建不通过),Hadoop 采用 2.6.0 官方二进制包(与 2.4.0 目标兼容,仅作类路径提供者使用,无需启动任何 Hadoop 服务),Hive 采用"官方 0.13.1 发行包的第三方依赖 + InMobi fork 的 7 个 hive jar"组合。整套组合下服务启动正常、查询全链路执行成功。

二、系统准备

安装基础组件并确认 Java 环境:

sudo apt-get update
sudo apt-get install -y openjdk-8-jdk maven curl unzip
java -version

实测输出:

openjdk version "1.8.0_504" ...

若系统存在多个 Java 版本,将默认版本切换到 8:

sudo update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/bin/java
sudo update-alternatives --set javac /usr/lib/jvm/java-8-openjdk-amd64/bin/javac

规划目录结构并创建工作目录:

sudo mkdir -p /opt/lens /opt/hadoop /opt/hive /opt/downloads

目录用途约定:/opt/lens 存放 Lens 发行树,/opt/hadoop 存放 Hadoop 发行树,/opt/hive 存放 Hive 依赖树,/opt/downloads 存放下载产物。以下所有命令以 root 执行(生产环境建议使用专用账号并相应收紧权限)。

动手下载前建议先做一轮环境预检,确认磁盘、内存与端口余量。实测环境执行结果:

df -h /opt | tail -1
free -m | sed -n 2p
(curl -s -o /dev/null -m 2 http://localhost:9999/ && echo "9999 已被占用") || echo "9999 可用"

实测回显:

overlay         786G  488G  264G  65% /
Mem:           32050       19871         935          29       11243       11594
9999 可用

预检口径:三棵发行树加 Maven 仓库合计约 2.5 GB(Hadoop 186 MB、Lens 43 MB、本地仓库在构建路线下会膨胀),磁盘留出 10 GB 以上余量;服务端堆上限 512 MB 加上查询执行时 Hive/MapReduce 子进程的开销,评估环境 2 GB 内存即可,承载真实查询建议 4 GB 起步;9999(API)与 19999(管理)两个端口空闲是启动成功的硬前提。

三、下载与完整性校验

Lens 2.2.0-beta 的发行档位于 Apache 归档目录(注意目录名与文件名的版本号写法不同):

cd /opt/downloads
wget https://archive.apache.org/dist/incubator/lens/2.2-beta-incubating/apache-lens-2.2.0-beta-incubating-bin.tar.gz
wget https://archive.apache.org/dist/incubator/lens/2.2-beta-incubating/apache-lens-2.2.0-beta-incubating-bin.tar.gz.sha512
wget https://archive.apache.org/dist/incubator/lens/2.2-beta-incubating/apache-lens-2.2.0-beta-incubating-source-release.zip

确认文件大小:

ls -la /opt/downloads/apache-lens-*

实测输出:

-rw-r--r-- 1 root root 43129316 ... apache-lens-2.2.0-beta-incubating-bin.tar.gz
-rw-r--r-- 1 root root      192 ... apache-lens-2.2.0-beta-incubating-bin.tar.gz.sha512
-rw-r--r-- 1 root root  2313109 ... apache-lens-2.2.0-beta-incubating-source-release.zip

官方校验文件采用 BSD 风格书写(文件名开头、大写十六进制、按 16 位分组)。核对方法是把官方值与本地计算值统一为小写连续字符串比对:

cat apache-lens-2.2.0-beta-incubating-bin.tar.gz.sha512
sha512sum apache-lens-2.2.0-beta-incubating-bin.tar.gz

实测官方文件内容(节选格式):

apache-lens-2.2.0-beta-incubating-bin.tar.gz:
C4D9CC20 80862D64 5CCCC3BA 6276DB1F AB771854 7AB33075 475D13E6 DD41A244 09211A7C
 4088DCDD 26494307 B3C14525 40B2BF0B 211B5933 D5F7C17B 3358CC87

本地计算结果:

c4d9cc2080862d645cccc3ba6276db1fab7718547ab33075475d13e6dd41a24409211a7c4088dcdd26494307b3c1452540b2bf0b211b5933d5f7c17b3358cc87

两者逐位一致,包完整性确认。二进制包 41MB、源码包 2.2MB,普通链路即可完成下载。校验这一步在退役项目上的分量比常规安装更重:归档服务器不再有下载加速节点,大文件往往经多次续传才下载完成,任何一次续传错位都可能产生静默损坏,SHA512 的碰撞抗性也足以覆盖恶意篡改场景。建议把"下载完成即校验、校验通过再解压"固化为脚本第一步,并保留校验文件与下载文件同目录存放,便于日后复验。

四、解压 Lens 与 Hadoop 发行包

解压 Lens 二进制包并确认目录结构:

cd /opt/lens && tar -xzf /opt/downloads/apache-lens-2.2.0-beta-incubating-bin.tar.gz
ls apache-lens-2.2.0-beta-incubating-bin/

实测输出为 client 与 server 两个子目录(另有许可文件若干)。server 目录下包含 bin(启动脚本)、conf(配置)、conf-pseudo-distr(伪分布式示例配置)与 webapp(内含 lens-server.war)。conf-pseudo-distr 值得专门一提:它是面向伪分布式后端的完整示例配置集,与 conf 目录同构,怀疑配置改坏时可以用 diff 对比两目录同名文件快速定位自己改过什么,也可以在初次部署时整体复制其内容作为起点再做最小修改——这是退役项目留给维护者的高价值脚手架。接着下载并解压 Hadoop 2.6.0(约 186MB,作类路径来源使用):

cd /opt/downloads
wget https://archive.apache.org/dist/hadoop/common/hadoop-2.6.0/hadoop-2.6.0.tar.gz
ls -la hadoop-2.6.0.tar.gz

实测大小为 195,257,604 字节。解压到规划位置:

tar -xzf hadoop-2.6.0.tar.gz -C /opt/hadoop
ls /opt/hadoop/hadoop-2.6.0/share/hadoop/

实测 share/hadoop 下存在 common、hdfs、mapreduce、yarn 等子目录,启动脚本将从中挑选 jar 追加类路径,无需改动任何 Hadoop 配置,也不需要启动 Hadoop 的任何服务进程。

五、构造 Hive 依赖目录(关键步骤)

这是 Lens 部署中最容易失败的一步。目标目录是 /opt/hive-inmobi/lib,其组成原则为:取 Apache 官方 Hive 0.13.1 发行包 lib 目录中的全部第三方依赖 jar,剔除其中所有 hive 自身的 jar,再叠加 InMobi fork 的 7 个 hive jar(版本 0.13.3-inm,与 Lens POM 锁定版本一致)。

第一步,下载官方 Hive 0.13.1(52MB)并解压:

cd /opt/downloads
wget https://archive.apache.org/dist/hive/hive-0.13.1/apache-hive-0.13.1-bin.tar.gz
tar -xzf apache-hive-0.13.1-bin.tar.gz -C /opt/hive
mv /opt/hive/apache-hive-0.13.1-bin /opt/hive/hive-0.13.1-bin

第二步,从 InMobi fork 仓库获取 7 个 hive jar 与对应 POM(GitHub 托管,路径为 releases/org/apache/hive/ 下的各构件目录):

mkdir -p /opt/inmobi && cd /opt/inmobi
for a in hive-cli hive-common hive-exec hive-metastore hive-serde hive-service hive-shims; do
  wget https://github.com/InMobi/mvn-repo/raw/master/releases/org/apache/hive/$a/0.13.3-inm/$a-0.13.3-inm.jar
  wget https://github.com/InMobi/mvn-repo/raw/master/releases/org/apache/hive/$a/0.13.3-inm/$a-0.13.3-inm.pom
done

第三步,组装目标目录:

mkdir -p /opt/hive-inmobi/lib
cd /opt/hive/hive-0.13.1-bin/lib
for j in *.jar; do case "$j" in hive-*) ;; *) cp "$j" /opt/hive-inmobi/lib/;; esac; done
cp /opt/inmobi/hive-{cli,common,exec,metastore,serde,service,shims}-0.13.3-inm.jar /opt/hive-inmobi/lib/
ls /opt/hive-inmobi/lib | wc -l

实测得到 62 个 jar,其中 datanucleus、libfb303、antlr 等第三方依赖来自官方 0.13.1,7 个 hive-*.jar 均为 0.13.3-inm 版本。若跳过 fork 替换、直接把官方 0.13.1 的 hive jar 提供给 Lens,服务启动会失败,实测报错为:

Exception in thread "main" java.lang.NoSuchFieldError: HIVE_SESSION_IMPL_CLASSNAME
        at org.apache.lens.server.LensServices.init(LensServices.java:190)

该字段只存在于 InMobi fork 的 HiveSession 接口中,是判断 Hive 依赖组装是否正确的标志性错误。

这步组装背后的机理值得展开,理解了它就不会在其它 Hive 版本组合上踩坑。Lens 服务端通过 HIVE_HOME 把整个 lib 目录追加进类路径,类路径上同名类的先后顺序由 jar 的追加顺序决定,因此"hive 自身 jar 必须且只能有一套版本"是硬约束——官方 0.13.1 与 fork 0.13.3-inm 的 hive-exec 等核心 jar 若同时存在,先被加载的那套胜出,后加载的接口签名差异就以 NoSuchFieldError 这类链接期错误的形式爆发。第三方依赖(datanucleus、antlr、libfb303 等)则对版本相对宽容,直接复用官方 0.13.1 发行包里的版本即可,无需逐个追平 fork 的依赖清单。另一个实操细节:组装完成的校验不能只看 jar 总数(62 这个数字随官方包小版本浮动),应以 ls /opt/hive-inmobi/lib | grep "^hive-" 确认 hive 前缀 jar 恰好 7 个且版本号全部为 0.13.3-inm 为准,这个口径才是链接错误的根因所在。

六、配置与启动

编辑 server/conf/lens-env.sh,写入运行环境变量(该文件自带各变量的注释示例,按需取消注释或追加):

export LENS_SERVER_OPTS="-XX:PermSize=256m -XX:MaxPermSize=256m"
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export HADOOP_HOME=/opt/hadoop/hadoop-2.6.0
export HIVE_HOME=/opt/hive-inmobi
export LENS_SERVER_HEAP="-Xms256m -Xmx512m"

各变量作用:LENS_SERVER_OPTS 为固定 JVM 选项;JAVA_HOME 供 Hadoop 子进程脚本使用(缺失会导致查询执行阶段的 MapReduce 子任务报 Error: JAVA_HOME is not set and could not be found.,实测确认);HADOOP_HOME 与 HIVE_HOME 为类路径来源;LENS_SERVER_HEAP 为堆内存设置,启动脚本 lens-config.sh 会把它并入 LENS_OPTS 传给 JVM。

关于 LENS_SERVER_OPTS 中的 PermSize 两项要多说一句:它们是 JDK 7 时代的永久代设置,在 JDK 8 上已被移除,实测用这两个参数调用 java 时会打印警告 OpenJDK 64-Bit Server VM warning: ignoring option PermSize=256m; support was removed in 8.0(MaxPermSize 同理)。也就是说在本文的 JDK 8 环境里这两行实际不起作用,服务进程行里能看到参数但无效果,保留它们无害(发行默认值如此),理解了警告来源就不会在排障时被误导;若追求干净,可将其替换为 JDK 8 的元空间参数(-XX:MetaspaceSize),Lens 的类加载数量不大,默认元空间上限也够用。

启动服务:

cd /opt/lens/apache-lens-2.2.0-beta-incubating-bin/server
bin/lens-ctl start

实测输出:

Adding hadoop libs in classpath from /opt/hadoop/hadoop-2.6.0
HIVE_HOME is set, adding /opt/hive-inmobi/lib/* into lens classpath
Started lens server!

启动脚本的行为值得记录:缺 HADOOP_HOME 时直接拒绝并报 Cannot find hadoop installation: \$HADOOP_HOME or \$HADOOP_PREFIX must be set or hadoop must be in the path;有 HADOOP_HOME 而缺 HIVE_HOME 时报 HIVE_HOME is not set. Set HIVE_HOME and try again。两个前置检查都通过后才拉起 Java 进程。

启动过程的正常日志特征:服务日志 lensserver.log 中先打印版本横幅(project.version: 2.2.0-beta-incubating),随后逐个初始化服务,出现 Hive driver inited、JDBC Driver configured、Driver for ... is loaded 与 Initialized services: [CLIService, event, metrics, stats, session, query, metastore, scheduler, quota...],最后 Grizzly 监听器绑定 0.0.0.0:9999 与 0.0.0.0:19999 两个端口。初始化期间会有一条预期内的警告 No persist path available for service:session/query/metastore/scheduler/quota,表示未配置服务状态持久化目录,单机评估可忽略。

配置改动后的生效验证有一套固定口径,建议形成习惯:改 lens-env.sh 只影响下次启动,需先 stop 再 start,中途只 restart 一次即可,反复启停会在 logs 目录堆积多组 lensserver.out 文件徒增排查噪音;生效与否的判定点有三个——ps 命令行中的堆参数(对应 LENS_SERVER_HEAP)、启动日志的 classpath 追加行(对应 HADOOP_HOME/HIVE_HOME)、以及 lsof 或 netstat 中 9999/19999 的监听进程号与 server.pid 一致。三个点都对上,才谈得上"配置已生效",只看端口通不通会把加载错依赖目录这类问题漏掉。

七、启动验证

服务健康检查:

curl -s http://localhost:9999/lensapi/admin/status

实测返回:

STARTED

同时验证管理端点与会话资源:

curl -s -o /dev/null -w "stack: %{http_code}\n" http://localhost:9999/lensapi/admin/stack
curl -s -o /dev/null -w "session: %{http_code}\n" http://localhost:9999/lensapi/session
curl -s -o /dev/null -w "metastore cubes: %{http_code}\n" http://localhost:9999/lensapi/metastore/cubes

实测三个状态码分别为 200、200、400——metastore 资源不带会话参数返回 400 属预期的参数校验行为。确认堆内存设置生效:

ps -ef | grep [j]ava | grep -oE "\-Xms[0-9]+[mM] \-Xmx[0-9]+[mM]"

实测输出:

-Xms256m -Xmx512m

与 lens-env.sh 中的 LENS_SERVER_HEAP 完全一致。最后用客户端完成端到端验证:

cd /opt/lens/apache-lens-2.2.0-beta-incubating-bin/client
printf "show databases\nexit\n" | bin/lens-cli.sh

实测输出:

lens-shell>show databases
default
lens-shell>exit

CLI 自动与本地服务建立会话并返回 Lens 元数据库列表,部署链路全部打通。

7.1 运行期日志布局

部署完成后应建立对日志目录的日常认知。server/logs/ 实测包含以下成员:

lensserver.log                    # 服务主日志:启动序列、驱动加载、查询路由
lensserver-requests.log           # HTTP 请求/响应逐条转储(含请求头与状态行)
query-stats.log                   # 查询统计,按小时轮转为 query-stats.log.2026-10-14-20 等
lensserver.out.<时间戳>            # 标准输出,每次启动新开一组,历史批次保留
server.pid                        # 当前服务进程号

日常巡检建议按三层走:先 curl -s http://localhost:9999/lensapi/admin/status 确认 STARTED;再看 lensserver.log 尾部有无 ERROR(重点关注 Estimate failed 与 driver 相关行);最后核对 server.pid 与实际进程号一致、lensserver.out 最新批次的启动序列无异常退出。lensserver-requests.log 体量增长快(每条 HTTP 交互都落盘),长期运行的环境应纳入 logrotate 或定期截断,否则它会成为磁盘占用的主力。

7.2 停止与重启的验证闭环

bin/lens-ctl stop 实测输出 Stopped lens server! 后,完整验证应包含三步:管理端点连接被拒(curl 返回 000)、ps -ef | grep [j]ava 无残留进程、server.pid 中记录的进程号已不复存活。重启后除 status 检查外,建议顺手执行一次 show databases 级别的 CLI 端到端确认,因为驱动初始化失败类问题有时不影响端口监听却会阻断查询——只看 status 会漏掉这一类故障。

八、源码构建路线(可选)

需要审计或定制时,可从源码包构建。解压源码并执行 Maven 构建:

cd /opt/lens-src && unzip /opt/downloads/apache-lens-2.2.0-beta-incubating-source-release.zip
cd apache-lens-2.2.0-beta-incubating
mvn clean package -DskipTests -Dcheckstyle.skip=true -Dmaven.javadoc.skip=true

构建有两个前置处理。其一,配置中央仓库的国内加速代理(在 /root/.m2/settings.xml 中把对 central 的请求转发到 https://maven.aliyun.com/repository/public),实测直连中央仓库约 17kB/s,改走该代理后整体提速一个数量级,全量构建约 12 分钟完成。其二,POM 锁定的 hive 0.13.3-inm 系列构件(hive-cli、hive-common、hive-exec、hive-hcatalog-core、hive-metastore、hive-serde、hive-service、hive-shims 及父 POM org.apache.hive:hive、org.apache.hive.hcatalog:hive-hcatalog)不在中央仓库,Maven 会到 POM 声明的第三方仓库拉取;若网络受限,可按第五节的地址手工下载后按 Maven 布局放入 /root/.m2/repository/org/apache/hive/ 下对应目录(hcatalog 构件位于 hcatalog/hive-hcatalog-core 路径),再重新构建。实测处理完成后构建结果为:

[INFO] BUILD SUCCESS
[INFO] Total time:  12:11 min

产物位于 lens-dist/target/apache-lens-2.2.0-beta-incubating-bin.tar.gz(实测 43,210,084 字节),结构与官方发行包一致,可替换第四节的官方包走同样的部署流程。

关于两个前置处理的背景再补充几点。仓库加速的原因在于构建需要从中央仓库拉取数百个传递依赖,2015 年代的 POM 还会触发额外的元数据查询,直连境外仓库的带宽在跨境链路上波动极大,代理仓库把这种波动抹平;settings.xml 中 mirrorOf 配置为 central 即可,不要写成 * 以免影响其它私有仓库。手工预置 fork 构件时,Maven 布局要求目录路径与构件坐标严格对应(groupId 逐级成目录、目录名即版本号),并把 .pom 与 .jar 成对放入,缺 .pom 时 Maven 会按远程仓库缺失处理而继续找代理,反而拖慢构建;预置后可用 mvn dependency:get -Dartifact=org.apache.hive:hive-exec:0.13.3-inm 快速验证本地仓库是否可解析。构建产物与官方包的体积差(43,210,084 对 43,129,316 字节)来自构建时间戳与个别资源文件的再生成,属正常现象;若追求逐字节一致还需额外配置,无实际必要。

九、常见安装问题排查

启动报 NoSuchFieldError: HIVE_SESSION_IMPL_CLASSNAME。 Hive 依赖目录里混入了 Apache 官方 0.13.1 的 hive jar。按第五节重组目录:第三方依赖取自官方包,hive 自身 jar 必须全部换为 0.13.3-inm。

启动报 Cannot find hadoop installation。 HADOOP_HOME 未设置或路径下无 Hadoop 发行树。确认 /opt/hadoop/hadoop-2.6.0/share/hadoop 结构完整。

启动报 HIVE_HOME is not set。 同理,确认 HIVE_HOME 指向构造好的 /opt/hive-inmobi。

服务能启动但查询报 Error: JAVA_HOME is not set and could not be found. 服务进程本身用 JAVA_BIN 启动不受影响,但执行查询时 Hive 的 MapReduce 子进程脚本需要 JAVA_HOME。在 lens-env.sh 中 export JAVA_HOME 后重启服务,实测即恢复。该错误的原始输出可在 server/query_logs/<会话句柄>/<操作句柄>.err 中找到。

CLI 提交查询报 Error Code: 3001。 查询不符合 Hive 语法解析(如使用了 VALUES 子句等非 Hive 写法)。改写为 Hive 方言语法后重试。

JDBC 驱动估计失败(日志出现 Estimate failed for driver JDBC)。 默认 JDBC 驱动配置面向 MySQL 且 URI 为空。可在 lens-site.xml 中配置 lens.driver.jdbc.driver.class 与 lens.driver.jdbc.db.uri 指向 HSQLDB 等本地库;实测配置后估计阶段仍有空指针,查询会路由到 Hive 驱动执行,不影响评估使用。

下载速度过慢。 186MB 的 Hadoop 包建议使用多连接下载工具;归档站点响应偏慢属正常,保留校验文件核对即可。

安装两个版本 Hive 依赖的取舍。 若服务器上已有运行其它应用的 Hive 发行目录,不要直接把 HIVE_HOME 指过去:Lens 要求 hive 自身 jar 全部为 0.13.3-inm,与现役 Hive 共目录必然引入版本冲突(见第五节的链接错误机理)。正确做法是按本文构造独立的 /opt/hive-inmobi,两个应用各用各的依赖树,互不干扰。

query_logs 目录随使用持续膨胀。 每条查询按会话与操作句柄生成 .err/.out 文件,长期运行后文件数以千计。它们是排障的重要证据,不建议自动删除;可按月打包迁移至归档目录,或在评估环境中设置 cron 只保留最近 N 天。

端口占用导致启动失败。 默认使用 9999/19999 端口,可在 lens-site.xml 调整 lens.server.port 相关配置,或停用占用方后重启。

启动日志满屏 PermSize 警告。 JDK 8 上 -XX:PermSize 与 -XX:MaxPermSize 已被移除,实测打印 ignoring option PermSize=256m; support was removed in 8.0 级别的警告后继续运行。该警告无害,参数来自发行默认的 LENS_SERVER_OPTS;介意输出噪音可将其替换为 -XX:MetaspaceSize 系列,不影响功能。

部署看似成功但查询全挂。 服务端口监听正常不代表驱动可用:Hive 驱动初始化失败(如依赖目录中混入不兼容 jar)可能只表现为查询提交后长时间无响应或统一报错。判定方法:status 返回 STARTED 后再执行一条最小查询(如 select 1+1)做端到端确认;失败时取 server/logs/lensserver.log 中 Hive driver inited 之后的第一条异常与 query_logs 中对应操作句柄的 .err 文件联合定位。

十、卸载方式

先停止服务再删除目录。停止服务:

cd /opt/lens/apache-lens-2.2.0-beta-incubating-bin/server
bin/lens-ctl stop

实测输出 Stopped lens server!,停止后管理端点连接被拒绝(curl 返回 000),确认进程退出。停止是否彻底建议用三重证据确认:进程表无 java 残留、9999/19999 端口不再监听、logs/server.pid 记录的进程号失效——Lens 停止脚本不会删除 server.pid 文件,只看文件存在与否会误判。然后按需清理各目录:

rm -rf /opt/lens/apache-lens-2.2.0-beta-incubating-bin
rm -rf /opt/lens-src
rm -rf /opt/hive-inmobi /opt/hive
rm -rf /opt/hadoop
rm -f /tmp/lensreports -r
rm -rf /opt/downloads/apache-lens-* /opt/downloads/hadoop-* /opt/downloads/apache-hive-*

清理之外还有三处分散残留需要按需处理:/root/.m2/repository 中手工预置的 org/apache/hive 构件与本次构建拉取的传递依赖(构建路线专用,纯二进制部署不会有);/tmp/lensreports 下按句柄落盘的查询结果目录;lens-env.sh 写入的 profile 级环境变量(若曾写入 /etc/profile.d)。卸载验证的标准命令组合:

curl -s -o /dev/null -w "%{http_code}" http://localhost:9999/lensapi/admin/status
ps -ef | grep [j]ava
ls /opt/lens /opt/hive-inmobi /opt/hadoop

三项回显分别为连接失败、无 java 进程、目录均不存在,即环境已完全清理。卸载顺序上先 stop 再 rm 的纪律与所有 Java 服务一致:避免运行中进程持有 query_logs 与结果目录句柄导致删除瞬间残留。

若源码构建过程中做过 Maven 依赖预置,还应清理 /root/.m2/repository/org/apache/hive 下的 0.13.3-inm 构件与 /root/.m2/settings.xml 中的加速代理配置,避免影响其他项目的构建。卸载 Hadoop/Hive 若为 Lens 专用,随 Lens 一并移除即可;JDK 8 如无其他使用方可由 apt-get purge openjdk-8-jdk 移除。

十一、常见问题(FAQ)

1. 必须用 JDK 8 吗? 是。Lens 按该时代构建,源码 README 明确说明更高版本 JDK 构建不通过;运行环境实测 JDK 8 正常。同时必须在 lens-env.sh 导出 JAVA_HOME 供查询子进程使用。

2. 为什么启动脚本要求 HADOOP_HOME/HIVE_HOME? 服务端 war 不捆绑 Hive/Hadoop jar,运行时类路径由这两个目录追加。这是 Lens 的发行设计,不是缺陷;好处是后端依赖可独立升级替换。

3. 能否直接用 Apache 官方 Hive 0.13.1 做 HIVE_HOME? 不能直接用。Lens 使用的 HiveSession 接口字段只在 InMobi fork(0.13.3-inm)中存在,官方包会触发 NoSuchFieldError。正确做法是官方包第三方依赖加 fork hive jar 组合,见第五节。

4. 需要真正启动 Hadoop 集群吗? 不需要。Hadoop 目录仅作为 jar 来源;配合 fs.defaultFS=file:/// 与 mapreduce.framework.name=local 的本地模式配置,内嵌 Hive 能在本机完成查询执行,实测单机查询返回正常。

5. 堆内存 256-512MB 如何确认已生效? 启动后执行 ps -ef | grep [j]ava 查看进程命令行,实测可见 -Xms256m -Xmx512m;该值来自 lens-env.sh 的 LENS_SERVER_HEAP,经 lens-config.sh 汇入 JVM 参数。

6. 服务默认监听哪些端口? 实测日志显示绑定 0.0.0.0:9999 与 0.0.0.0:19999 两个监听器;REST API 与管理接口按默认 base url 走 9999 端口的 /lensapi 路径,健康检查 GET /lensapi/admin/status 返回 STARTED。

7. 源码构建失败的常见原因? 两类:中央仓库直连过慢导致超时(配置加速代理解决);hive 0.13.3-inm 构件缺失(预置本地仓库解决)。构件清单与本地仓库路径见第八节。

8. 校验文件格式为什么和 sha512sum 输出不一样? 官方采用 BSD 风格(含文件名、大写、分组排版),内容与标准 sha512sum 十六进制值一致,统一为小写连续字符串比对即可,实测逐位吻合。补充一个实用技巧:比对前可用 tr 'A-Z' 'a-z' 把 BSD 文本归一化,或直接对官方校验文件做 grep -o 提取散列串再与本地值 diff,避免手工肉眼比对一百二十八个字符。之所以用 SHA512 而不是更常见的 MD5,是 2014 年后 Apache 发行规范的统一要求(同一时期 Lenya 归档还是 MD5),属于两代规范的时间断层,做归档下载时应按各项目实际提供的校验类型准备工具。

9. 服务状态持久化警告要处理吗? 启动日志的 "No persist path available" 警告表示未启用服务状态持久化目录,单机评估可忽略;长期运行应在 lens-site.xml 配置持久化路径以免重启丢失排队查询状态。这条警告逐个服务出现一次(session、query、metastore、scheduler、quota 各一条),属于启动期正常输出的一部分,巡检时不要把它误读为多实例异常。

10. 卸载会影响系统其他部分吗? 不会。Lens 体系全部落在自建目录(/opt/lens、/opt/hive-inmobi、/opt/hadoop 等)与用户级 Maven 仓库,按第十节逐项删除即可;如 JDK 8 为 Lens 专用再一并移除。

11. 启动警告 PermSize support was removed in 8.0 需要处理吗? 不需要。该警告来自发行默认 LENS_SERVER_OPTS 中的永久代参数,JDK 8 直接忽略它们,服务照常运行;介意噪音可换成 -XX:MetaspaceSize 系列,其余变量无需改动。

12. 端到端验证只看 admin/status 够吗? 不够。status 返回 STARTED 只说明编排层就绪,驱动初始化失败类问题可能不阻断监听却让所有查询失败。标准验证链应为 status 检查加一条最小查询(CLI 执行 select 1+1)加日志复核三层,任何一层异常都应回到第九节排障。

13. 归档站点下载慢,能否用国内下载站替代? 发行档的权威来源只有 archive.apache.org;国内下载站通常只同步现行发行版,已退役项目的归档路径大多没有同步。折中方案是先在归档站获取官方 SHA512 校验值(校验文件很小,慢速下载可接受),再从任意可信渠道取得大文件本体,最后以校验值闭环——只要散列一致,文件即等同于官方原档。

参考链接