使用指南 - saas-search(运行与运维)
本文档聚焦运行与运维:服务启动/停止、日志查看、多环境切换、故障排查、Suggestion 索引运维。
开发与配置(环境入口、配置体系、Provider 架构、模块扩展规范)请优先阅读 docs/QUICKSTART.md。
目录
环境准备
系统要求
- 操作系统: Linux (推荐 CentOS 7+ / Ubuntu 18.04+)
- Python: 3.8+
- 内存: 建议 8GB+
- 磁盘: 10GB+ (包含模型文件)
- Elasticsearch: 8.x (可通过Docker运行)
安装依赖
1. 安装 Python 依赖与激活环境
推荐:使用项目根目录的 activate.sh 激活环境(会加载 .env)。当前仅支持 venv(.venv),不存在 Conda 回退。系统要求、Python 环境、生产凭证与 .env 模板见 QUICKSTART.md §1.4–1.8。
cd /data/saas-search
./scripts/create_venv.sh # 首次创建 venv(只需执行一次)
source activate.sh
模型服务采用独立环境(推荐):
cd /data/saas-search
./scripts/setup_embedding_venv.sh # .venv-embedding
./scripts/setup_reranker_venv.sh # .venv-reranker
./scripts/setup_cnclip_venv.sh # .venv-cnclip
TEI 文本向量服务使用 Docker 容器:
# GPU(需 nvidia-container-toolkit)
TEI_USE_GPU=1 ./scripts/start_tei_service.sh
# CPU
TEI_USE_GPU=0 ./scripts/start_tei_service.sh
专项说明:
docs/TEI_SERVICE说明文档.mddocs/CNCLIP_SERVICE说明文档.md
2. 启动Elasticsearch
方式1: 使用Docker(推荐)
docker run -d \
--name elasticsearch \
-p 9200:9200 \
-e "discovery.type=single-node" \
-e "ES_JAVA_OPTS=-Xms2g -Xmx2g" \
elasticsearch:8.11.0
方式2: 本地安装
3. 配置环境变量(支持多环境)
创建 .env 文件(以本地 / prod 环境为例):
# MySQL配置
DB_HOST=120.79.247.228
DB_PORT=3316
DB_DATABASE=saas
DB_USERNAME=saas
DB_PASSWORD=your_password
# Elasticsearch配置
ES_HOST=http://localhost:9200
ES_USERNAME=essa
ES_PASSWORD=your_es_password
# Redis配置(可选,用于缓存)
REDIS_HOST=localhost
REDIS_PORT=6479
REDIS_PASSWORD=your_redis_password
# DeepL翻译API(可选)
DEEPL_AUTH_KEY=your_deepl_auth_key
# 运行环境(用于区分 prod / uat / test / dev)
RUNTIME_ENV=prod
# ES 索引命名空间前缀(用于按环境隔离索引,prod 通常留空)
ES_INDEX_NAMESPACE=
# API服务配置
API_HOST=0.0.0.0
API_PORT=6002
服务启动
方式1: 一键启动(推荐)
cd /data/saas-search
./run.sh
这个脚本会自动:
- 创建日志目录
- 启动核心服务(backend/indexer/frontend)
- 写入 PID 到
logs/*.pid - 执行健康检查
启动完成后,访问:
- 前端界面: http://localhost:6003
- 后端API: http://localhost:6002
- API文档: http://localhost:6002/docs
- 索引API: http://localhost:6004/docs
可选:全功能模式(同时启动 embedding/translator/reranker/tei):
START_EMBEDDING=1 START_TRANSLATOR=1 START_RERANKER=1 START_TEI=1 ./run.sh
方式2: 统一控制脚本(推荐)
# 查看状态
./scripts/service_ctl.sh status
# 启动核心服务(默认)
./scripts/service_ctl.sh start
# 启动指定服务
./scripts/service_ctl.sh start backend indexer frontend translator reranker tei
# 停止全部服务(含可选服务)
./scripts/service_ctl.sh stop
# 重启
./scripts/service_ctl.sh restart
方式3: 分步启动(单环境)
启动后端服务
./scripts/start_backend.sh
后端API会在 http://localhost:6002 启动(使用当前 .env 中的 ES_HOST / DB_HOST / RUNTIME_ENV / ES_INDEX_NAMESPACE)
启动前端服务
./scripts/start_frontend.sh
前端界面会在 http://localhost:6003 启动
方式4: 多环境示例(prod / uat)
假设有两套环境:
- prod:正式环境,RUNTIME_ENV=prod,ES_INDEX_NAMESPACE 为空
- uat:联调环境,RUNTIME_ENV=uat,ES_INDEX_NAMESPACE=uat_
可以在项目根目录准备两个配置文件:
.env.prod:
RUNTIME_ENV=prod
ES_INDEX_NAMESPACE=
ES_HOST=http://prod-es:9200
DB_HOST=prod-mysql
...
.env.uat:
RUNTIME_ENV=uat
ES_INDEX_NAMESPACE=uat_
ES_HOST=http://uat-es:9200
DB_HOST=uat-mysql
...
启动不同环境时:
# 启动 UAT 后端 + 索引服务
cp .env.uat .env
./scripts/start_backend.sh
./scripts/start_indexer.sh
# 启动 PROD 后端 + 索引服务
cp .env.prod .env
./scripts/start_backend.sh
./scripts/start_indexer.sh
方式5: 手动启动
启动后端API服务
python -m api.app \
--host 0.0.0.0 \
--port 6002 \
--es-host http://localhost:9200 \
--reload
启动前端服务(可选)
# 使用Python简单HTTP服务器
cd frontend
python -m http.server 6003
停止服务
# 推荐:统一停止
./scripts/stop.sh
# 或使用统一控制脚本
./scripts/service_ctl.sh stop
服务端口
| 服务 | 端口 | URL |
|---|---|---|
| Elasticsearch | 9200 | http://localhost:9200 |
| Backend API | 6002 | http://localhost:6002 |
| Indexer API | 6004 | http://localhost:6004 |
| Frontend Web | 6003 | http://localhost:6003 |
| Embedding (optional) | 6005 | http://localhost:6005 |
| TEI (optional) | 8080 | http://localhost:8080 |
| Translation (optional) | 6006 | http://localhost:6006 |
| Reranker (optional) | 6007 | http://localhost:6007 |
| API Docs | 6002 / 6004 | http://localhost:6002/docs / http://localhost:6004/docs |
配置说明
环境配置文件 (.env)
主要配置项说明:
# Elasticsearch配置
ES_HOST=http://localhost:9200
ES_USERNAME=essa
ES_PASSWORD=your_es_password
# MySQL配置
DB_HOST=120.79.247.228
DB_PORT=3316
DB_DATABASE=saas
DB_USERNAME=saas
DB_PASSWORD=your_password
# Redis配置(可选,用于缓存)
REDIS_HOST=localhost
REDIS_PORT=6479
REDIS_PASSWORD=your_redis_password
# DeepL翻译API
DEEPL_AUTH_KEY=your_deepl_auth_key
# API服务配置
API_HOST=0.0.0.0
API_PORT=6002
# Indexer服务配置
INDEXER_HOST=0.0.0.0
INDEXER_PORT=6004
# Optional service ports
EMBEDDING_PORT=6005
TRANSLATION_PORT=6006
RERANKER_PORT=6007
# Optional startup switches (for run.sh / service_ctl.sh)
START_EMBEDDING=0
START_TRANSLATOR=0
START_RERANKER=0
修改配置
- 编辑
.env文件 - 重启相关服务
查看日志
日志文件位置
日志文件存储在 logs/ 目录下:
logs/backend.log- 后端服务日志logs/indexer.log- 索引服务日志logs/frontend.log- 前端服务日志logs/embedding.log- 向量服务日志(可选)logs/translator.log- 翻译服务日志(可选)logs/reranker.log- 重排服务日志(可选)logs/search_engine.log- 应用主日志(按天轮转)logs/errors.log- 错误日志(按天轮转)
查看实时日志
# 查看后端日志
tail -f logs/backend.log
# 查看前端日志
tail -f logs/frontend.log
# 查看应用主日志
tail -f logs/search_engine.log
# 查看错误日志
tail -f logs/errors.log
日志级别
日志级别可以通过环境变量 LOG_LEVEL 设置:
# 在 .env 文件中设置
LOG_LEVEL=DEBUG # DEBUG, INFO, WARNING, ERROR, CRITICAL
日志轮转
日志文件按天自动轮转,保留30天的历史日志。
测试验证
1. 健康检查
curl http://localhost:6002/admin/health
预期响应:
{
"status": "healthy",
"elasticsearch": "connected"
}
2. 索引统计
curl http://localhost:6002/admin/stats -H "X-Tenant-ID: 162"
3. 简单搜索测试
curl -X POST http://localhost:6002/search/ \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: 162" \
-d '{
"query": "玩具",
"size": 10
}'
或者通过查询参数:
curl -X POST "http://localhost:6002/search/?tenant_id=2" \
-H "Content-Type: application/json" \
-d '{
"query": "玩具",
"size": 10
}'
4. 带过滤器的搜索
curl -X POST http://localhost:6002/search/ \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: 162" \
-d '{
"query": "玩具",
"size": 10,
"filters": {
"category.keyword": ["玩具", "益智玩具"]
},
"range_filters": {
"price": {"gte": 50, "lte": 200}
}
}'
5. 分面搜索测试
curl -X POST http://localhost:6002/search/ \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: 162" \
-d '{
"query": "玩具",
"size": 10,
"facets": [
{"field": "category.keyword", "size": 15},
{"field": "vendor.keyword", "size": 15}
]
}'
6. 图片搜索测试
curl -X POST http://localhost:6002/search/image \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: 162" \
-d '{
"image_url": "https://oss.essa.cn/example.jpg",
"size": 10
}'
7. 前端界面测试
访问 http://localhost:6003 或 http://localhost:6002/ 进行可视化测试。
注意: 所有搜索接口都需要通过 X-Tenant-ID 请求头或 tenant_id 查询参数指定租户ID。
8. Suggestion 索引与接口使用
8.1 构建 Suggestion 索引(Phase 2:全量 + 增量)
Suggestion 索引会从:
- ES 商品索引:
title.{lang},qanchors.{lang} - MySQL 日志表:
shoplazza_search_log.query(含language、request_params)
聚合生成版本化索引并发布 alias:
- 物理索引:
{ES_INDEX_NAMESPACE}search_suggestions_tenant_{tenant_id}_v<timestamp> - 读别名:
{ES_INDEX_NAMESPACE}search_suggestions_tenant_{tenant_id}_current
在项目根目录执行(以 tenant_id=162 为例):
# 1) 全量重建(版本化 + alias 发布)
./scripts/build_suggestions.sh 162 \
--mode full \
--days 30 \
--publish-alias \
--keep-versions 2
# 2) 增量更新(watermark + overlap)
./scripts/build_suggestions.sh 162 \
--mode incremental \
--overlap-minutes 30
可选参数:
--days:回溯日志天数(默认 30)--batch-size:扫描商品索引的批大小(默认 500)--min-query-len:参与 suggestion 的最小查询长度(默认 1)--overlap-minutes:增量窗口重叠分钟数(默认 30)--bootstrap-if-missing:增量模式下若缺少 active index 则自动全量初始化(默认 true)
建议在商品索引构建完成、日志正常写入一段时间后执行一次全量构建,然后按天/小时增加增量构建任务。
8.2 调用 Suggestion 接口
全量构建完成后,可直接通过 /search/suggestions 获取自动补全结果:
# UAT 环境(本地或 UAT 集群)
curl "http://localhost:6002/search/suggestions?q=iph&size=5&language=en" \
-H "X-Tenant-ID: 162"
# PROD 环境(域名 / 端口按实际部署调整)
curl "https://api.yourdomain.com/search/suggestions?q=iph&size=5&language=en" \
-H "X-Tenant-ID: 162"
8.3 商品索引构建(search_products,多环境例子)
以 tenant_id=162 为例,分别在 UAT / PROD 构建商品索引。
UAT 环境(索引前缀 uat_)
cd /data/saas-search
# 1. 切换到 UAT 环境配置
cp .env.uat .env
# 2. 启动 indexer 服务(如尚未启动)
./scripts/start_indexer.sh
# 3. 可选:重建索引结构(会删除旧索引)
./scripts/create_tenant_index.sh 162
# 实际创建的索引名为:uat_search_products_tenant_162
# 4. 导入商品数据(全量索引)
curl -X POST "http://localhost:6004/indexer/reindex" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "162",
"batch_size": 500
}'
PROD 环境(无前缀)
cd /data/saas-search
# 1. 切换到 PROD 环境配置
cp .env.prod .env
# 2. 启动 indexer 服务
./scripts/start_indexer.sh
# 3. 可选:重建索引结构(search_products_tenant_162)
./scripts/create_tenant_index.sh 162
# 4. 导入商品数据
curl -X POST "http://localhost:6004/indexer/reindex" \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "162",
"batch_size": 500
}'
完成后:
- UAT 环境商品索引:
uat_search_products_tenant_162 - PROD 环境商品索引:
search_products_tenant_162
两套环境的搜索 / suggestion API 调用完全一致,只是连接到各自的后端 / ES。
接口返回结构详见 docs/搜索API对接指南.md 的“3.7 搜索建议接口”章节。
常见问题
Q1: MySQL连接失败
症状: Failed to connect to MySQL
解决方案:
# 检查MySQL服务状态
mysql -h 120.79.247.228 -P 3316 -u saas -p -e "SELECT 1"
# 检查配置
cat .env | grep DB_
Q2: Elasticsearch连接失败
症状: Failed to connect to Elasticsearch
解决方案:
# 检查ES服务状态
curl http://localhost:9200
# 检查ES版本
curl http://localhost:9200 | grep version
# 确认配置
cat .env | grep ES_
Q3: 服务启动失败
症状: Address already in use 或端口被占用
解决方案:
# 查看占用端口的进程
lsof -i :6002 # 后端
lsof -i :6003 # 前端
lsof -i :9200 # ES
# 杀掉进程
kill -9 <PID>
# 或修改端口配置
Q4: 搜索无结果
症状: 搜索返回空结果
解决方案:
# 检查ES中是否有数据
curl http://localhost:9200/search_products/_count
# 检查tenant_id过滤是否正确
curl -X POST http://localhost:6002/search/ \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: 162" \
-d '{"query": "*", "size": 10, "debug": true}'
Q5: 前端无法连接后端
症状: CORS错误
解决方案:
- 确保后端在 http://localhost:6002 运行
- 检查浏览器控制台错误信息
- 检查后端日志中的CORS配置
Q6: 翻译不工作
症状: 翻译返回原文
解决方案:
- 检查DEEPL_AUTH_KEY是否正确
- 如果没有API key,系统会使用mock模式(返回原文)
相关文档
- 测试数据构造文档:
TEST_DATA_GUIDE.md- 如何构造和导入测试数据 - API接口文档:
API_INTEGRATION_GUIDE.md- 完整的API对接指南 - 字段说明文档:
INDEX_FIELDS_DOCUMENTATION.md- 索引字段详细说明 - 设计文档:
设计文档.md- 系统架构和设计说明 - README:
README.md- 项目概述和快速开始
文档版本: v2.0
最后更新: 2024-12