Skip to content

Commit 554e816

Browse files
committed
[fix](build) Stabilize Hive shared-volume baseline workflow
### What problem does this PR solve? Issue Number: None Related PR: None Problem Summary: Consolidate the Hive docker startup, shared-volume baseline, and OSS baseline publishing changes into a single commit. This keeps Hive metadata on a stable shared hostname, makes rebuild/refresh work with shared container names, versions the downloaded baseline cache and OSS filenames, and bumps the baseline version used by CI. ### Release note None ### Check List (For Author) - Test: Manual test - Verified hive2/hive3 rebuild and refresh on aliyun shared-volume environment - Published updated hive2/hive3 baseline tarballs to OSS with versioned filenames - Behavior changed: Yes (Hive shared-volume startup and baseline restore now use stable host identity and versioned baseline artifacts) - Does this need documentation: No
1 parent 3943667 commit 554e816

File tree

12 files changed

+1054
-182
lines changed

12 files changed

+1054
-182
lines changed

docker/thirdparties/docker-compose/hive/README.md

Lines changed: 304 additions & 89 deletions
Large diffs are not rendered by default.
Lines changed: 384 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,384 @@
1+
<!--
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either implied. See the License for the specific
16+
language governing permissions and limitations
17+
under the License.
18+
-->
19+
20+
# Hive Docker 环境
21+
22+
Doris thirdparty 回归测试使用的 Hive2/Hive3 Docker Compose 模板与引导脚本。
23+
24+
英文版: [README.md](README.md)
25+
26+
---
27+
28+
## 架构
29+
30+
Hive 启动被拆分为三层互相独立的抽象:
31+
32+
### Layer 1 — Docker 服务
33+
34+
所有服务均使用 `network_mode: host`,端口直接暴露在宿主机上。
35+
36+
| 服务 | 职责 | Hive3 端口 | Hive2 端口 |
37+
|---|---|---|---|
38+
| `hive-server` | HiveServer2 (SQL/JDBC 入口) | `13000` | `10000` |
39+
| `hive-metastore` | Hive Metastore (HMS) | `9383` | `9083` |
40+
| `hive-metastore-postgresql` | Metastore 元数据库 | `5732` | `5432` |
41+
| `namenode` | HDFS NameNode | `8320` | `8020` |
42+
| `datanode` | HDFS DataNode |||
43+
44+
容器名前缀由 `CONTAINER_UID`(定义在 `custom_settings.env`)指定。
45+
例如 `CONTAINER_UID=doris-jack-` → 容器名为 `doris-jack-hive3-server`
46+
47+
### Layer 2 — 刷新模块(`--hive-modules`
48+
49+
每个模块对应 `scripts/data/` 下的一个目录或一组专用脚本。
50+
模块是**增量刷新**的:只有内容 SHA 发生变化的模块才会被重新执行。
51+
52+
| 模块 | 源路径 | 内容 |
53+
|---|---|---|
54+
| `default` | `scripts/data/default/` | `default` 库中的基础外部表 |
55+
| `multi_catalog` | `scripts/data/multi_catalog/` | 多格式、多路径的外部表用例 |
56+
| `partition_type` | `scripts/data/partition_type/` | 各类分区类型覆盖(int、string、date 等)|
57+
| `statistics` | `scripts/data/statistics/` | 表统计与空表统计相关用例 |
58+
| `tvf` | `scripts/data/tvf/` | TVF 测试数据(上传到 HDFS)|
59+
| `regression` | `scripts/data/regression/` | 特殊回归数据集(serde、分隔符等)|
60+
| `test` | `scripts/data/test/` | 轻量级冒烟测试数据 |
61+
| `preinstalled_hql` | `scripts/create_preinstalled_scripts/*.hql` | 约 77 个 HQL 文件,通过 `xargs -P` 并行执行 |
62+
| `view` | `scripts/create_view_scripts/create_view.hql` | View 定义 |
63+
64+
### Layer 3 — Bootstrap 组(`HIVE_BOOTSTRAP_GROUPS`
65+
66+
控制模块内哪些文件会被纳入刷新范围。
67+
68+
|| 含义 |
69+
|---|---|
70+
| `common` | Hive2 与 Hive3 共用 |
71+
| `hive2_only` | 仅 Hive2 使用的文件(列在 `bootstrap/hive2_only.*.list`|
72+
| `hive3_only` | 仅 Hive3 使用的文件(列在 `bootstrap/hive3_only.*.list`|
73+
| `all` | 以上所有(未指定时的默认值)|
74+
75+
各版本默认的 bootstrap 组:
76+
- Hive2:`common,hive2_only`
77+
- Hive3:`common,hive3_only`
78+
79+
---
80+
81+
## 状态存储:Docker 命名卷 + OSS Baseline
82+
83+
Hive 运行态(HDFS 数据、Postgres Metastore、模块 SHA 记录)存放在**每个版本 4 个 Docker 命名卷**中,不再使用宿主机 bind mount:
84+
85+
|| 挂载位置 |
86+
|---|---|
87+
| `<CONTAINER_UID><hive_version>-namenode` | NameNode 元数据 |
88+
| `<CONTAINER_UID><hive_version>-datanode` | DataNode 数据块 |
89+
| `<CONTAINER_UID><hive_version>-pgdata` | Hive Metastore Postgres 数据 |
90+
| `<CONTAINER_UID><hive_version>-state` | `/mnt/state` — baseline 版本号 + 各模块 SHA 文件 |
91+
92+
生命周期:
93+
- `--hive-mode fast` / `refresh`:卷在多次运行间保留。
94+
- `--hive-mode rebuild`:卷被删除(`docker volume rm`)后重建为空。
95+
96+
### 首次启动:Baseline 恢复
97+
98+
当卷为空时(全新 CI 主机,或执行过 `rebuild`),脚本不会从零完整 bootstrap,而是从预先构建的 baseline tarball 恢复:
99+
100+
1. 先在 `${HIVE_BASELINE_TARBALL_CACHE:-/tmp/hive-baseline-cache}/<hive_version>-baseline.tar.gz` 查找本地缓存。
101+
2. 未命中缓存时,从 `${HIVE_BASELINE_URL_PREFIX}/<hive_version>-baseline-<version>-<arch>.tar.gz` 下载。默认前缀为 `https://doris-thirdparty.oss-cn-beijing.aliyuncs.com/thirdparties/hive-baseline`。可通过 `HIVE_BASELINE_TARBALL_URL` 强制覆盖完整 URL。
102+
3. 使用单个 `alpine tar` 容器同时挂载 4 个卷解包 —— tar 流直接写入卷的挂载点。
103+
104+
相关环境变量:
105+
106+
| 变量 | 默认值 | 作用 |
107+
|---|---|---|
108+
| `HIVE_BASELINE_URL_PREFIX` | `https://doris-thirdparty.oss-cn-beijing.aliyuncs.com/thirdparties/hive-baseline` | baseline tarball 下载的基础 URL |
109+
| `HIVE_BASELINE_TARBALL_URL` | *(空)* | 完整 URL,优先级高于按前缀拼接 |
110+
| `HIVE_BASELINE_TARBALL_CACHE` | `/tmp/hive-baseline-cache` | 下载 tarball 的本地缓存目录 |
111+
| `HIVE_BASELINE_VERSION` | `20260415` | 写入 `/mnt/state/baseline.version`;不一致时强制重建 baseline |
112+
113+
### 生成新的 baseline tarball
114+
115+
在一次完整 bootstrap 成功后,停止容器并运行:
116+
117+
```bash
118+
sudo docker compose -p "${CONTAINER_UID}hive3" \
119+
-f docker/thirdparties/docker-compose/hive/hive-3x.yaml down
120+
121+
bash docker/thirdparties/docker-compose/hive/scripts/snapshot-hive-baseline.sh \
122+
"${CONTAINER_UID}hive3" /tmp/hive3-baseline.tar.gz
123+
```
124+
125+
然后把得到的 tarball 上传到 `<HIVE_BASELINE_URL_PREFIX>/hive3-baseline-<version>-<arch>.tar.gz``hive2` 同理)。
126+
127+
---
128+
129+
## 使用方式
130+
131+
### 启动 / 停止
132+
133+
```bash
134+
# 启动 Hive3(默认为 refresh 模式)
135+
./docker/thirdparties/run-thirdparties-docker.sh -c hive3
136+
137+
# 启动 Hive2
138+
./docker/thirdparties/run-thirdparties-docker.sh -c hive2
139+
140+
# 同时启动两者
141+
./docker/thirdparties/run-thirdparties-docker.sh -c hive2,hive3
142+
143+
# 停止 Hive3
144+
./docker/thirdparties/run-thirdparties-docker.sh -c hive3 --stop
145+
```
146+
147+
### 启动模式(`--hive-mode`
148+
149+
| 模式 | 行为 |
150+
|---|---|
151+
| `fast` | 若 stack 已 healthy 则跳过 compose up;完全跳过数据刷新 |
152+
| `refresh` | stack healthy 时跳过 compose up;只重跑 SHA 发生变化的模块/HQL 文件 *(默认)* |
153+
| `rebuild` | 拆掉 stack,清空所有卷,冷启动 |
154+
155+
```bash
156+
# fast:数据没变,只需要保证 stack 在跑
157+
./docker/thirdparties/run-thirdparties-docker.sh -c hive3 --hive-mode fast
158+
159+
# refresh:不拆 stack,增量拾取 HQL/脚本变化(默认)
160+
./docker/thirdparties/run-thirdparties-docker.sh -c hive3 --hive-mode refresh
161+
162+
# rebuild:从零开始
163+
./docker/thirdparties/run-thirdparties-docker.sh -c hive3 --hive-mode rebuild
164+
```
165+
166+
### 按模块限定刷新范围(`--hive-modules`
167+
168+
只刷新关心的模块:
169+
170+
```bash
171+
# 只重跑变化的 preinstalled HQL 文件(并行)
172+
./docker/thirdparties/run-thirdparties-docker.sh -c hive3 \
173+
--hive-mode refresh --hive-modules preinstalled_hql
174+
175+
# 刷新两个特定模块
176+
./docker/thirdparties/run-thirdparties-docker.sh -c hive3 \
177+
--hive-mode refresh --hive-modules default,multi_catalog
178+
179+
# 显式刷新所有模块
180+
./docker/thirdparties/run-thirdparties-docker.sh -c hive3 \
181+
--hive-mode refresh --hive-modules all
182+
```
183+
184+
---
185+
186+
## 开发者指南
187+
188+
### 如何添加测试数据
189+
190+
按数据存放方式,有两种模式。
191+
192+
#### 模式 A — `run.sh`(HDFS 数据 + DDL)
193+
194+
当测试数据文件需要上传到 HDFS 时使用这种模式。
195+
196+
1. 在合适的模块下新建目录:
197+
```
198+
scripts/data/<module>/<your_dataset>/
199+
├── run.sh # 必需:模块刷新时被执行
200+
└── <data files> # csv、parquet、orc 等
201+
```
202+
203+
2. `run.sh` 必须是**幂等的**(反复运行不出问题):
204+
```bash
205+
#!/bin/bash
206+
set -x
207+
CUR_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
208+
209+
# 仅在 HDFS 上不存在时才上传
210+
hadoop fs -mkdir -p /user/doris/preinstalled_data/your_dataset
211+
if [[ -z "$(hadoop fs -ls /user/doris/preinstalled_data/your_dataset 2>/dev/null)" ]]; then
212+
hadoop fs -put "${CUR_DIR}"/data/* /user/doris/preinstalled_data/your_dataset/
213+
fi
214+
215+
# 建表(drop 后再 create,保证幂等)
216+
hive -e "
217+
DROP TABLE IF EXISTS your_table;
218+
CREATE EXTERNAL TABLE your_table (...)
219+
STORED AS PARQUET
220+
LOCATION '/user/doris/preinstalled_data/your_dataset';
221+
"
222+
```
223+
224+
3. 若仅供 Hive2 或 Hive3 使用,把 `run.sh` 的相对路径加入对应清单:
225+
```
226+
bootstrap/hive2_only.run_sh.list
227+
bootstrap/hive3_only.run_sh.list
228+
```
229+
230+
#### 模式 B — `create_preinstalled_scripts/`(仅 HQL)
231+
232+
适用于不需要上传 HDFS 文件的场景(指向已有 HDFS 数据的外部表,或通过 INSERT VALUES 写入内部表)。
233+
234+
1. 新建 `scripts/create_preinstalled_scripts/runNN.hql`
235+
```sql
236+
use default;
237+
238+
DROP TABLE IF EXISTS `your_new_table`;
239+
CREATE EXTERNAL TABLE `your_new_table` (
240+
id INT,
241+
name STRING
242+
)
243+
STORED AS PARQUET
244+
LOCATION '/user/doris/preinstalled_data/existing_path';
245+
```
246+
247+
2. 约定:
248+
- 始终先 `DROP TABLE IF EXISTS``CREATE` —— 不要只写 `CREATE IF NOT EXISTS`
249+
- 用下一个未占用的 `runNN` 编号
250+
- 仅 Hive2/Hive3 使用时,把相对路径加入 `bootstrap/hive2_only.preinstalled_hql.list``bootstrap/hive3_only.preinstalled_hql.list`
251+
- 若与 TPCH 相关,加入 `bootstrap/tpch.preinstalled_hql.list`
252+
253+
3. 触发一次刷新让它生效:
254+
```bash
255+
./docker/thirdparties/run-thirdparties-docker.sh -c hive3 \
256+
--hive-mode refresh --hive-modules preinstalled_hql
257+
```
258+
259+
---
260+
261+
### 如何接入 HiveServer2 进行调试
262+
263+
所有容器都是 `network_mode: host`,端口在宿主机上可直接访问。
264+
265+
#### 容器内使用 beeline
266+
267+
```bash
268+
# 进入 hive-server 容器
269+
docker exec -it ${CONTAINER_UID}hive3-server bash
270+
271+
# 通过 beeline 连接(PATH 里的 hive shim 会自动走这里)
272+
beeline -u "jdbc:hive2://localhost:13000/default" -n root
273+
274+
# 也可以直接用 hive 别名
275+
hive -e "show databases;"
276+
hive -e "show tables in default;"
277+
hive -f /path/to/your.hql
278+
```
279+
280+
#### 宿主机上使用 beeline
281+
282+
```bash
283+
# 宿主机上的 beeline 已在 PATH 中;使用本地回环地址即可
284+
beeline -u "jdbc:hive2://127.0.0.1:13000/default" -n root
285+
```
286+
287+
#### 在容器外执行临时 HQL
288+
289+
```bash
290+
# 执行单条查询
291+
docker exec ${CONTAINER_UID}hive3-server \
292+
beeline -u "jdbc:hive2://localhost:13000/default" -n root \
293+
-e "SELECT * FROM default.your_table LIMIT 10;"
294+
295+
# 执行 HQL 文件(文件需在容器内或已挂载的路径下)
296+
docker exec ${CONTAINER_UID}hive3-server \
297+
hive -f /mnt/scripts/create_preinstalled_scripts/run02.hql
298+
```
299+
300+
#### 查看 HDFS
301+
302+
```bash
303+
# 列出 HDFS 顶层目录
304+
docker exec ${CONTAINER_UID}hadoop3-namenode \
305+
hadoop fs -ls /user/doris/
306+
307+
# 检查指定路径是否存在
308+
docker exec ${CONTAINER_UID}hadoop3-namenode \
309+
hadoop fs -ls /user/doris/preinstalled_data/your_dataset/
310+
```
311+
312+
#### 直连 Metastore PostgreSQL
313+
314+
```bash
315+
# 直接连接 metastore 库(Hive3 是 5732 端口)
316+
psql -h 127.0.0.1 -p 5732 -U postgres -d metastore \
317+
-c "SELECT TBL_NAME, DB_ID FROM TBLS LIMIT 20;"
318+
```
319+
320+
---
321+
322+
## 日志与调试
323+
324+
| 日志文件 | 内容 |
325+
|---|---|
326+
| `docker/thirdparties/logs/start_hive3.log` | Hive3 完整启动日志 |
327+
| `docker/thirdparties/logs/start_hive2.log` | Hive2 完整启动日志 |
328+
329+
开启详细 xtrace:
330+
331+
```bash
332+
HIVE_DEBUG=1 ./docker/thirdparties/run-thirdparties-docker.sh -c hive3 --hive-mode refresh
333+
```
334+
335+
每个阶段结束时会打印耗时:
336+
```
337+
[14:02:31] [hive3] compose up done took=18s
338+
[14:02:49] [hive3] init-hive-baseline begin
339+
[14:03:11] [hive3] init-hive-baseline done took=22s
340+
[14:03:11] [hive3] refresh-hive-modules begin (mode=refresh modules=all)
341+
[14:05:44] [hive3] refresh-hive-modules done took=153s
342+
```
343+
344+
---
345+
346+
## 故障排查
347+
348+
**Metastore 健康检查失败**
349+
- 确认 `${CONTAINER_UID}hive3-metastore-postgresql` 已 healthy:`docker ps`
350+
- 查看启动日志:`tail -100 docker/thirdparties/logs/start_hive3.log`
351+
352+
**HiveServer2 连不上**
353+
- 检查容器是否在运行:`docker ps | grep hive3-server`
354+
- 测试端口:`nc -z 127.0.0.1 13000`
355+
- 查看容器内 HS2 日志:`docker exec ${CONTAINER_UID}hive3-server tail -50 /tmp/hive-server2.log`
356+
357+
**JuiceFS format/init 失败**
358+
- 确认 `JFS_CLUSTER_META` 可达(默认为 `mysql://root:123456@(127.0.0.1:3316)/juicefs_meta`
359+
- 视需要 override:`export JFS_CLUSTER_META=<your_uri>`
360+
361+
**Refresh 明显变慢**
362+
- 看是哪些模块被重跑;若全都在跑,说明 SHA 不匹配,走了完整刷新
363+
- 收窄范围:`--hive-modules preinstalled_hql`
364+
- 结合上面的耗时日志定位慢阶段
365+
366+
**容器被硬杀后状态残留**
367+
- state 目录可能写了一半;使用 `--hive-mode rebuild` 重置干净
368+
369+
**Baseline 下载慢或失败**
370+
- 确认能访问 `HIVE_BASELINE_URL_PREFIX`(默认是阿里云 OSS)
371+
- 手动把 tarball 放到 `${HIVE_BASELINE_TARBALL_CACHE:-/tmp/hive-baseline-cache}/<hive_version>-baseline.tar.gz` 即可跳过下载
372+
- 改用镜像源:`export HIVE_BASELINE_URL_PREFIX=https://your-mirror/path`
373+
- 完全关闭 baseline 恢复:`export HIVE_BASELINE_URL_PREFIX=`(卷会从零完整 bootstrap)
374+
375+
**手动查看或删除卷**
376+
```bash
377+
# 列出某个版本的 4 个卷
378+
docker volume ls | grep "${CONTAINER_UID}hive3-"
379+
380+
# 删除全部 4 个(等价于 --hive-mode rebuild 的清理步骤)
381+
for s in namenode datanode pgdata state; do
382+
docker volume rm -f "${CONTAINER_UID}hive3-${s}"
383+
done
384+
```

0 commit comments

Comments
 (0)