
### 目标说明

**Ubuntu 单机单节点服务器**上安装 **Elasticsearch 9.3.1（9.x 最新小版本）** 的安装与基础调优文档。

- 不依赖 GPU（只用 CPU + bfloat16 向量）
- 使用官方 APT 源安装，自动带上自带的 JDK（满足 9.3 的要求）
- 适用于 Ubuntu 20.04/22.04/24.04 等常见版本
- 单机单节点模式：`discovery.type: single-node`

---

### 1. 系统与前置检查

- 操作系统：`Ubuntu 20.04+`（推荐 22.04 / 24.04）
- 需要 root 或 `sudo` 权限
- 确保系统时间正确、网络能访问 `artifacts.elastic.co`

```bash
lsb_release -a     # 查看 Ubuntu 版本
curl -I https://artifacts.elastic.co
```

---

### 2. 添加 Elasticsearch 9.x 官方 APT 仓库

#### 2.1 导入 GPG 公钥

```bash
sudo mkdir -p /usr/share/keyrings

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch \
  | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
```

#### 2.2 添加 9.x APT 源

```bash
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/9.x/apt stable main" \
  | sudo tee /etc/apt/sources.list.d/elastic-9.x.list
```

#### 2.3 更新包索引

```bash
sudo apt-get update
```

---

### 3. 安装 Elasticsearch 9.3.1

默认 `apt install elasticsearch` 会安装当前 9.x 仓库里的最新小版本（例如 9.3.1）。

```bash
sudo apt-get install elasticsearch
```

安装完成后，可以确认版本：

```bash
/usr/share/elasticsearch/bin/elasticsearch --version
# 预期显示: 9.3.1 ...
```

> 说明：  
> - 安装包自带并使用自己的 JDK（目前为 22），不依赖系统的 OpenJDK 17。  
> - 不需要自己配置 `JAVA_HOME`，除非有特殊需求。

---

### 4. 基础配置（单机单节点）

编辑 `elasticsearch.yml`（路径 `/etc/elasticsearch/elasticsearch.yml`），调整最基本的选项：

```bash
sudo vim /etc/elasticsearch/elasticsearch.yml
```

常用设置示例（仅示意关键行）：

```yaml
cluster.name: searchengine-cluster
node.name: node-1

network.host: 0.0.0.0
http.port: 9200

# 单机开发用（生产集群请改成多节点配置）
discovery.type: single-node

# 安全相关（按你当前 8.18 的做法决定是否开）
xpack.security.enabled: false
```

> 如果后续扩展为多节点集群，需要去掉 `discovery.type: single-node`，并按官方文档配置 `cluster.initial_master_nodes`、`seed_hosts` 等参数。

---

### 5. 使用 bfloat16 半精度向量的注意事项

- **前提：必须是 Elasticsearch 9.3+**。  
- 你的项目中，9.3 集群创建索引时，要使用已修改过的 `mappings/search_products.json`（`dense_vector` 增加 `element_type: "bfloat16"`）。  
- 在这台新机器的 9.3 集群上：
  - 创建索引时用 bfloat16 版 mapping；
  - 从 MySQL 重新同步数据。

这一部分是应用层的事，和 ES 安装本身无冲突，只要确保 **老 8.18 集群继续用原 mapping，新 9.3 集群用新 mapping** 即可。

---

### 6. 启动与开机自启

#### 6.1 手动启动 / 停止

```bash
# 启动
sudo systemctl start elasticsearch

# 查看状态
sudo systemctl status elasticsearch

# 停止
sudo systemctl stop elasticsearch
```

#### 6.2 设置开机自启

```bash
sudo systemctl enable elasticsearch
```

---

### 7. 验证服务是否正常

#### 7.1 本机访问

```bash
curl http://127.0.0.1:9200
```

预期返回类似：

```json
{
  "name" : "node-1",
  "cluster_name" : "searchengine-cluster",
  "cluster_uuid" : "...",
  "version" : {
    "number" : "9.3.1",
    ...
  },
  "tagline" : "You Know, for Search"
}
```

#### 7.2 远程访问（如有）

如果你在 `elasticsearch.yml` 里把 `network.host` 配成了 `0.0.0.0`，且机器安全组 / 防火墙允许 9200 端口，被访问方可以：

```bash
curl http://<es-server-ip>:9200
```

---

### 8. Kibana 9.x 安装与配置（单机）

> 说明：Kibana 版本必须与 Elasticsearch 大版本一致，这里以 9.3.1 为例，使用同一个 9.x APT 仓库。

#### 8.1 安装 Kibana

前面已经添加了 `elastic-9.x` APT 源，这里直接安装 Kibana：

```bash
sudo apt-get install kibana
```

安装完成后，可通过下面命令查看版本（可选）：

```bash
/usr/share/kibana/bin/kibana --version
```

#### 8.2 Kibana 基础配置

编辑 `kibana.yml`（默认路径 `/etc/kibana/kibana.yml`），至少确认以下几项：

```bash
sudo vim /etc/kibana/kibana.yml
```

常用示例（单机、关闭安全的开发环境）：

```yaml
server.host: "0.0.0.0"          # 允许外部访问，如只本机用可改为 "localhost"
server.port: 5601

elasticsearch.hosts: ["http://127.0.0.1:9200"]  # 指向本机 ES

# 如果 ES 开启了 xpack.security，需要在这里配置账号密码
# elasticsearch.username: "kibana_system"
# elasticsearch.password: "your_password"
```

> 生产环境建议：
> - 打开 Elasticsearch 的安全功能（`xpack.security.enabled: true`），用官方向导生成用户和证书；
> - Kibana 使用 `kibana_system` 用户连接 ES，并通过 HTTPS 访问；
> - `server.host` 不要暴露为 0.0.0.0，配合防火墙 / 反向代理限制访问来源。

#### 8.3 启动与开机自启 Kibana

```bash
# 启动 Kibana
sudo systemctl start kibana

# 查看状态
sudo systemctl status kibana

# 设置开机自启
sudo systemctl enable kibana
```

#### 8.4 验证 Kibana 访问

浏览器访问：

```text
http://<kibana-server-ip>:5601
```

如果 ES 未启用安全，首次打开一般会直接进入 Kibana 首页；  
如果启用了安全机制，将提示登录，使用你在 ES 初始化时创建的账号密码（如 `elastic` 用户）。

---

### 9. 与现有 saas-search 项目集成

在这台新机器上跑你的 saas-search 项目时：

- 环境变量或配置里的 ES 地址需要指向这台机器，例如：
  - `ES_HOST=http://127.0.0.1:9200`
- 按你项目已有脚本执行索引初始化和数据导入（在 9.3 上推荐使用 bfloat16 版 mapping）：
  - 创建索引：使用 `mappings/search_products.json`（bfloat16 版本）
  - 推荐导入流程：`./scripts/create_tenant_index.sh <tenant_id>` + `POST /indexer/reindex`

---

### 10. 常见问题提示

- **端口 9200 无法访问**
  - 检查 `systemctl status elasticsearch` 是否正常运行；
  - 检查 `network.host` 是否配置为可访问地址；
  - 检查防火墙（`ufw`、安全组）是否放行 9200。
- **版本不是 9.3.1**
  - 确认你添加的是 `https://artifacts.elastic.co/packages/9.x/apt`；
  - `apt-cache policy elasticsearch` 查看当前仓库里的版本；如有旧版本仓库，需要清理旧的 `elastic-*.list` 文件。

---

### 11. 性能与系统配置优化（单机节点）

> 以下为单机节点在物理机 / 大内存云主机上的推荐基础调优，参考了 8.18 版本的线上配置。具体数值请根据机器内存大小和实际压测结果微调。

#### 10.1 JVM 堆内存设置

编辑 `jvm.options`（或单独的 options 文件），为 ES 分配合适的堆内存，一般建议：

- 堆内存占物理内存的 1/2 左右，但不要超过 32GB  
- 例如 64GB 物理内存的机器：

```bash
sudo vim /etc/elasticsearch/jvm.options
```

示例（根据实际内存调整）：

```text
-Xms32g
-Xmx32g
```

修改完成后需要重启 Elasticsearch 生效。

#### 10.2 Elasticsearch 内部缓存相关配置

在 `/etc/elasticsearch/elasticsearch.yml` 中，根据机器内存和查询特征，控制 fielddata 与 query cache 占比，例如：

```yaml
# Fielddata Cache（主要用于排序、聚合）
indices.fielddata.cache.size: 40%   # 占物理内存的 40% 上限

# Query Cache（用于相同过滤条件的命中缓存）
indices.queries.cache.size: 30%     # 占堆内存的 30% 上限
```

对于你当前的电商搜索场景，如果聚合比较多（分类 / 规格分面等），可以适当提高 fielddata cache；如果过滤条件组合多而重复率不高，可以适当降低 query cache。

#### 10.3 内核参数（sysctl）优化

编辑 `/etc/sysctl.conf`，追加如下内容（来自现有 8.18 生产配置，可直接沿用到 Ubuntu）：

```bash
sudo vim /etc/sysctl.conf
```

推荐配置示例：

```text
# tangwang - Elasticsearch 内核参数优化
# 最大文件句柄数
fs.file-max = 1000000

# 允许的 VMA 数量（映射的虚拟内存区域，用于 mmap 索引文件）
vm.max_map_count = 655360

# 脏页写回相关（削峰写入）
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5
vm.dirty_writeback_centisecs = 200
vm.dirty_expire_centisecs = 6000

# inode cache 回收权重
vm.vfs_cache_pressure = 200

# 尽可能少用 swap（内存充裕环境建议 0）
vm.swappiness = 0
```

修改后执行：

```bash
sudo sysctl -p
```

#### 10.4 文件句柄与进程数限制（limits.conf）

编辑 `/etc/security/limits.conf`，为所有用户（特别是运行 ES 的用户）提升文件描述符和进程数上限：

```bash
sudo vim /etc/security/limits.conf
```

示例（参考现有 8.18 配置）：

```text
# tangwang - ES 资源限制调优
* soft nofile 655350
* hard nofile 655350
root soft nofile 655350
root hard nofile 655350

* soft nproc 102400
* hard nproc 409600

# 允许进程锁定内存（配合后续如需 mlockall 等）
* soft memlock unlimited
* hard memlock unlimited
```

修改完成后，建议重新登录终端 / 重启服务，使新的 limits 生效。

#### 10.5 单机节点模式小结

单机单节点模式下，最关键的是：

- 在 `elasticsearch.yml` 中设置 `discovery.type: single-node`，避免 ES 等待集群选主；
- 为 ES 分配足够的堆和系统资源（JVM 堆 + sysctl + limits）；
- 使用 bfloat16 向量字段，减小内存与磁盘占用，有利于在线搜索性能；
- 通过你现有的压测脚本（搜索 QPS / 延迟、批量索引速度）验证上述参数，在此基础上微调即可。
