feat(core): services.yaml 启动配置 + _run.sh 统一参数透传
Step 1: init.txt → services.yaml - 新增 InitParser (yaml-cpp), 支持 YAML/TXT 双模式解析, 向后兼容 init.txt - 新增 services.yaml 声明式服务配置 (name/cmd/args/depends_on/sleep_before) - 改造 pmc_mtd.cpp 集成 InitParser, 支持目录/.yaml/.txt 三种路径模式 - Makefile 添加 InitParser 编译目标 + -lyaml-cpp 链接 - setup 脚本添加 libyaml-cpp-dev / yaml-cpp-devel 依赖 - core/_run.sh 改为 -i . (目录模式, 自动查找 services.yaml → init.txt) Step 2: 11 个 _run.sh 统一参数透传 - 8 个脚本改动: 追加 "$@" / 移除 sleep / 修引号 - waf 保留 -c config.yaml 作为脚本默认值 - services.yaml waf args 改为 [] 避免重复传递 - 开发方案文档: docs/reports/core_services_yaml_dev_doc.md
This commit is contained in:
1 parent
bba7ee3eb4
commit
08df3929b2
18 files changed
+1143
-41
No files matched your search
+1
-1
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
# Debian
|
# Debian
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install libsqlite3-dev libboost-all-dev libcurl4-gnutls-dev python3 python3-venv python3-pip g++ patchelf golang-go libportaudio-ocaml-dev libfreetype-dev
|
sudo apt install libsqlite3-dev libboost-all-dev libcurl4-gnutls-dev python3 python3-venv python3-pip g++ patchelf golang-go libportaudio-ocaml-dev libfreetype-dev libyaml-cpp-dev
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# RHEL / CentOS / Rocky / Fedora
|
# RHEL / CentOS / Rocky / Fedora
|
||||||
sudo dnf install -y boost-devel libcurl-devel python3 python3-pip gcc-c++ patchelf golang sqlite-devel freetype-devel
|
sudo dnf install -y boost-devel libcurl-devel python3 python3-pip gcc-c++ patchelf golang sqlite-devel freetype-devel yaml-cpp-devel
|
||||||
+1
-1
@@ -2,5 +2,5 @@
|
|||||||
cd "$(dirname "$0")" || exit
|
cd "$(dirname "$0")" || exit
|
||||||
source ./venv/bin/activate
|
source ./venv/bin/activate
|
||||||
#exec ./dnfs.bin
|
#exec ./dnfs.bin
|
||||||
exec python3 ai_review.py
|
exec python3 ai_review.py "$@"
|
||||||
|
|
||||||
+1
-1
@@ -3,6 +3,6 @@ cd "$(dirname "$0")" || exit
|
|||||||
source ./_setenv.sh
|
source ./_setenv.sh
|
||||||
source ./venv/bin/activate
|
source ./venv/bin/activate
|
||||||
export PATH=${PATH}:~/.aibox/skills
|
export PATH=${PATH}:~/.aibox/skills
|
||||||
exec python aibox.py $@
|
exec python aibox.py "$@"
|
||||||
|
|
||||||
|
|
||||||
+1
-3
@@ -4,7 +4,5 @@
|
|||||||
# 启动时从 confs(CONFS_HOST:CONFS_PORT,默认 127.0.0.1:8010)拉取配置。
|
# 启动时从 confs(CONFS_HOST:CONFS_PORT,默认 127.0.0.1:8010)拉取配置。
|
||||||
cd "$(dirname "$0")" || exit
|
cd "$(dirname "$0")" || exit
|
||||||
|
|
||||||
# 等待依赖服务启动(confs/db)
|
# sleep 已移至 services.yaml 的 sleep_before 字段统一管理
|
||||||
sleep 2
|
|
||||||
|
|
||||||
exec ./build/ca.out "$@"
|
exec ./build/ca.out "$@"
|
||||||
+1
-2
@@ -1,4 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
cd "$(dirname "$0")" || exit
|
cd "$(dirname "$0")" || exit
|
||||||
sleep 1
|
exec ./captcha2.bin "$@"
|
||||||
exec ./captcha2.bin
|
|
||||||
+8
-3
@@ -4,7 +4,7 @@ APP_NAME := nidus
|
|||||||
|
|
||||||
INSTL_DIRS := /usr/local/bin
|
INSTL_DIRS := /usr/local/bin
|
||||||
|
|
||||||
CONF_NAME := init.txt
|
CONF_NAME := services.yaml
|
||||||
|
|
||||||
CONF_DIR := /etc/Nidus
|
CONF_DIR := /etc/Nidus
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ CPP:= g++
|
|||||||
INCS:= -I include/
|
INCS:= -I include/
|
||||||
|
|
||||||
MY_LIBS := -L/usr/lib -lus_th -lus_http -lus_httpclient -lus_msg -lcurl
|
MY_LIBS := -L/usr/lib -lus_th -lus_http -lus_httpclient -lus_msg -lcurl
|
||||||
LIBS := -lpthread -lssl -lcrypto -lboost_program_options -lboost_json -lboost_thread -lboost_filesystem
|
LIBS := -lpthread -lssl -lcrypto -lboost_program_options -lboost_json -lboost_thread -lboost_filesystem -lyaml-cpp
|
||||||
|
|
||||||
CPPFLAGS := --std=c++20 -O3 -pipe #-Wall -Werror
|
CPPFLAGS := --std=c++20 -O3 -pipe #-Wall -Werror
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ $(shell mkdir -p $(BUILD_DIR))
|
|||||||
|
|
||||||
#--------
|
#--------
|
||||||
all: ${APP_NAME}.out
|
all: ${APP_NAME}.out
|
||||||
${APP_NAME}.out: $(BUILD_DIR)/main.o $(BUILD_DIR)/PPool.o $(BUILD_DIR)/ProcessTask.o $(BUILD_DIR)/HttpTask.o $(BUILD_DIR)/ConfsTask.o $(BUILD_DIR)/Tttask.o $(BUILD_DIR)/pmc_mtd.o $(BUILD_DIR)/subsys_call.o
|
${APP_NAME}.out: $(BUILD_DIR)/main.o $(BUILD_DIR)/PPool.o $(BUILD_DIR)/ProcessTask.o $(BUILD_DIR)/HttpTask.o $(BUILD_DIR)/ConfsTask.o $(BUILD_DIR)/Tttask.o $(BUILD_DIR)/pmc_mtd.o $(BUILD_DIR)/subsys_call.o $(BUILD_DIR)/InitParser.o
|
||||||
$(CPP) $^ $(MY_LIBS) $(LIBS) -o $@
|
$(CPP) $^ $(MY_LIBS) $(LIBS) -o $@
|
||||||
|
|
||||||
$(BUILD_DIR)/main.o: src/main.cpp
|
$(BUILD_DIR)/main.o: src/main.cpp
|
||||||
@@ -53,6 +53,9 @@ $(BUILD_DIR)/pmc_mtd.o: src/main/pmc_mtd.cpp
|
|||||||
$(BUILD_DIR)/subsys_call.o: src/main/subsys_call.cpp
|
$(BUILD_DIR)/subsys_call.o: src/main/subsys_call.cpp
|
||||||
$(CPP) $(CPPFLAGS) -c $^ $(INCS) -o $@
|
$(CPP) $(CPPFLAGS) -c $^ $(INCS) -o $@
|
||||||
|
|
||||||
|
$(BUILD_DIR)/InitParser.o: src/registry/InitParser.cpp
|
||||||
|
$(CPP) $(CPPFLAGS) -c $^ $(INCS) -o $@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
install: $(APP_NAME).out
|
install: $(APP_NAME).out
|
||||||
@@ -65,6 +68,7 @@ install: $(APP_NAME).out
|
|||||||
@echo "正在配置 $(APP_NAME)"
|
@echo "正在配置 $(APP_NAME)"
|
||||||
@mkdir -p $(CONF_DIR)
|
@mkdir -p $(CONF_DIR)
|
||||||
@cp $(CONF_NAME) $(CONF_DIR)/$(CONF_NAME)
|
@cp $(CONF_NAME) $(CONF_DIR)/$(CONF_NAME)
|
||||||
|
@cp init.txt $(CONF_DIR)/init.txt
|
||||||
@cp $(SRV_NAME) $(SRV_DIR)/$(SRV_NAME)
|
@cp $(SRV_NAME) $(SRV_DIR)/$(SRV_NAME)
|
||||||
@systemctl daemon-reload
|
@systemctl daemon-reload
|
||||||
@systemctl enable $(SRV_NAME)
|
@systemctl enable $(SRV_NAME)
|
||||||
@@ -77,6 +81,7 @@ uninstall:
|
|||||||
@
|
@
|
||||||
@rm -f $(INSTL_DIRS)/$(APP_NAME)
|
@rm -f $(INSTL_DIRS)/$(APP_NAME)
|
||||||
@rm -f $(CONF_DIRS)/$(CONF_NAME)
|
@rm -f $(CONF_DIRS)/$(CONF_NAME)
|
||||||
|
@rm -f $(CONF_DIRS)/init.txt
|
||||||
@rm -f -d ${CONF_DIRS}
|
@rm -f -d ${CONF_DIRS}
|
||||||
@
|
@
|
||||||
@systemctl stop $(SRV_NAME)
|
@systemctl stop $(SRV_NAME)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
cd "$(dirname "$0")" || exit
|
cd "$(dirname "$0")" || exit
|
||||||
export LD_LIBRARY_PATH=/lib:$LD_LIBRARY_PATH
|
export LD_LIBRARY_PATH=/lib:$LD_LIBRARY_PATH
|
||||||
./nidus.out -i init.txt --serve 5200 --confs 8010
|
./nidus.out -i . --serve 5200 --confs 8010
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace qing::registry {
|
||||||
|
|
||||||
|
/* 服务启动配置项
|
||||||
|
*
|
||||||
|
* 从 services.yaml 或 init.txt 解析出的单个服务声明。
|
||||||
|
* YAML 模式下包含完整的元数据;TXT 模式下仅 cmd 有值。
|
||||||
|
*/
|
||||||
|
struct ServiceConfig {
|
||||||
|
std::string name; /* 服务唯一标识 */
|
||||||
|
std::string cmd; /* 启动命令(如 bash /opt/.../_run.sh) */
|
||||||
|
std::vector<std::string> args; /* 传递给 _run.sh 的命令行参数 */
|
||||||
|
std::map<std::string, std::string> env; /* 启动前设置的环境变量 */
|
||||||
|
std::vector<std::string> depends_on; /* 依赖的服务名列表(未来 DAG 排序用) */
|
||||||
|
int sleep_before = 0; /* 启动前等待秒数 */
|
||||||
|
|
||||||
|
/* 拼接完整命令:cmd + " " + args... */
|
||||||
|
std::string toCommand() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 启动配置解析器
|
||||||
|
*
|
||||||
|
* 优先读 services.yaml(结构化声明),不存在则回退 init.txt(纯命令列表)。
|
||||||
|
* 两种格式都输出 std::vector<ServiceConfig>,调用方无需关心来源。
|
||||||
|
*/
|
||||||
|
class InitParser {
|
||||||
|
public:
|
||||||
|
/* 入口:传入配置目录(如 /etc/Nidus)
|
||||||
|
*
|
||||||
|
* 查找顺序:
|
||||||
|
* 1. <dir>/services.yaml → parseYaml()
|
||||||
|
* 2. <dir>/init.txt → parseTxt()
|
||||||
|
* 3. 都不存在 → 返回空 vector,调用方自行处理
|
||||||
|
*/
|
||||||
|
static std::vector<ServiceConfig> load(const std::string& dir);
|
||||||
|
|
||||||
|
/* 解析 services.yaml */
|
||||||
|
static std::vector<ServiceConfig> parseYaml(const std::string& path);
|
||||||
|
|
||||||
|
/* 解析 init.txt(向后兼容,每行一条命令,# 开头为注释) */
|
||||||
|
static std::vector<ServiceConfig> parseTxt(const std::string& path);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace qing::registry
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
# core/services.yaml
|
||||||
|
# 声明式服务启动配置(替代 init.txt)
|
||||||
|
# 如果本文件存在则优先使用,否则回退 init.txt
|
||||||
|
#
|
||||||
|
# 字段说明:
|
||||||
|
# name 服务唯一标识(用于日志和未来注册中心)
|
||||||
|
# cmd 启动命令(与 init.txt 每行格式一致)
|
||||||
|
# args 传递给 _run.sh 的命令行参数列表(可选)
|
||||||
|
# env 启动前设置的环境变量(可选)
|
||||||
|
# depends_on 依赖的服务名列表(未来 DAG 拓扑排序用,当前仅记录)
|
||||||
|
# sleep_before 启动前等待秒数(替代散落在 _run.sh 中的 sleep)
|
||||||
|
|
||||||
|
services:
|
||||||
|
# --- 数据层(最先启动) ---
|
||||||
|
- name: db2
|
||||||
|
cmd: bash /opt/micro_servers/db2/_run.sh
|
||||||
|
args: []
|
||||||
|
depends_on: []
|
||||||
|
sleep_before: 0
|
||||||
|
|
||||||
|
# --- AI 审核 ---
|
||||||
|
- name: ai_review
|
||||||
|
cmd: bash /opt/micro_servers/ai_review/_run.sh
|
||||||
|
args: []
|
||||||
|
depends_on: [db2]
|
||||||
|
sleep_before: 2
|
||||||
|
|
||||||
|
# --- 文件服务 ---
|
||||||
|
- name: dnfs2
|
||||||
|
cmd: bash /opt/micro_servers/dnfs2/_run.sh
|
||||||
|
args: []
|
||||||
|
depends_on: [db2, ai_review]
|
||||||
|
sleep_before: 0
|
||||||
|
|
||||||
|
# --- 邮件服务 ---
|
||||||
|
- name: smtp
|
||||||
|
cmd: bash /opt/micro_servers/smtp/_run.sh
|
||||||
|
args: []
|
||||||
|
depends_on: []
|
||||||
|
sleep_before: 2
|
||||||
|
|
||||||
|
# --- 前端静态资源 ---
|
||||||
|
- name: fsys
|
||||||
|
cmd: bash /opt/micro_servers/fsys/_run.sh
|
||||||
|
args: []
|
||||||
|
depends_on: []
|
||||||
|
sleep_before: 0
|
||||||
|
|
||||||
|
# --- 安全链路 ---
|
||||||
|
- name: waf
|
||||||
|
cmd: bash /opt/micro_servers/waf/_run.sh
|
||||||
|
args: [] # -c config.yaml 保留在 _run.sh 作为默认值
|
||||||
|
depends_on: [ca, gateway]
|
||||||
|
sleep_before: 0
|
||||||
|
|
||||||
|
- name: ca
|
||||||
|
cmd: bash /opt/micro_servers/ca/_run.sh
|
||||||
|
args: []
|
||||||
|
depends_on: [db2]
|
||||||
|
sleep_before: 2
|
||||||
|
|
||||||
|
- name: gateway
|
||||||
|
cmd: bash /opt/micro_servers/gateway/_run.sh
|
||||||
|
args: []
|
||||||
|
depends_on: [db2]
|
||||||
|
sleep_before: 2
|
||||||
|
|
||||||
|
# --- 验证码 ---
|
||||||
|
- name: captcha2
|
||||||
|
cmd: bash /opt/micro_servers/captcha2/_run.sh
|
||||||
|
args: []
|
||||||
|
depends_on: []
|
||||||
|
sleep_before: 1
|
||||||
|
|
||||||
|
# --- AI 工具箱 ---
|
||||||
|
- name: aibox
|
||||||
|
cmd: bash /opt/micro_servers/aibox/_run.sh
|
||||||
|
args: []
|
||||||
|
depends_on: []
|
||||||
|
sleep_before: 0
|
||||||
|
|
||||||
|
# --- 端口重定向(最后启动) ---
|
||||||
|
- name: redirect80
|
||||||
|
cmd: bash /opt/micro_servers/redirect80/_run.sh
|
||||||
|
args: []
|
||||||
|
depends_on: [waf]
|
||||||
|
sleep_before: 0
|
||||||
+1
-1
@@ -149,7 +149,7 @@ int main(int argc, char** argv) {
|
|||||||
("list", "list process all run") /* 列出运行中的进程 */
|
("list", "list process all run") /* 列出运行中的进程 */
|
||||||
("kill", po::value<int>(), "kill a process") /* 杀死一个进程 */
|
("kill", po::value<int>(), "kill a process") /* 杀死一个进程 */
|
||||||
/********* 子系统服务模式 ********/
|
/********* 子系统服务模式 ********/
|
||||||
("init,i", po::value<std::string>(), "self-init list") /* 输入自启动列表 */
|
("init,i", po::value<std::string>(), "self-init config (dir or .yaml/.txt file)") /* 输入自启动配置 */
|
||||||
("serve", po::value<int>(), "Run as http server") /* 启用http伺服器 */
|
("serve", po::value<int>(), "Run as http server") /* 启用http伺服器 */
|
||||||
("confs", po::value<int>(), "Run embedded confs rpc server"); /* 启用内嵌confs配置服务 */
|
("confs", po::value<int>(), "Run embedded confs rpc server"); /* 启用内嵌confs配置服务 */
|
||||||
|
|
||||||
|
|||||||
+50
-20
@@ -5,6 +5,12 @@
|
|||||||
#include <boost/property_tree/json_parser.hpp>
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
#include "main/PPool.hh"
|
#include "main/PPool.hh"
|
||||||
#include "main/pmc_mtd.hh"
|
#include "main/pmc_mtd.hh"
|
||||||
|
#include "registry/InitParser.hh"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
namespace qing {
|
namespace qing {
|
||||||
|
|
||||||
@@ -87,37 +93,61 @@ catch(std::exception& exp) {
|
|||||||
|
|
||||||
/* 解析自启动列表、添加自启动项
|
/* 解析自启动列表、添加自启动项
|
||||||
*
|
*
|
||||||
* 如果在解析过程中出错,只是打印异常? */
|
* 兼容两种格式:
|
||||||
|
* - services.yaml(结构化声明,含 args/env/depends_on/sleep_before)
|
||||||
|
* - init.txt(纯命令列表,每行一条 bash 命令,# 开头为注释)
|
||||||
|
*
|
||||||
|
* path 可以是:
|
||||||
|
* - 目录路径 → 自动查找 services.yaml 或 init.txt
|
||||||
|
* - .yaml 文件 → 按 YAML 解析
|
||||||
|
* - 其他文件 → 按 TXT 解析(向后兼容 init.txt)
|
||||||
|
*
|
||||||
|
* 如果在解析过程中出错,只是打印异常 */
|
||||||
void parse_self_init_list(std::string &path)
|
void parse_self_init_list(std::string &path)
|
||||||
try {
|
try {
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
std::ifstream file(path);
|
std::vector<registry::ServiceConfig> services;
|
||||||
if (!file.is_open()) { /* ---- 没能打开自启动文件 ---- */
|
|
||||||
std::cerr << "Failed to open self-init list" << std::endl;
|
if (fs::is_directory(path)) {
|
||||||
|
/* 目录模式:InitParser::load 自动查找 services.yaml → init.txt */
|
||||||
|
services = registry::InitParser::load(path);
|
||||||
|
} else if (path.size() > 5 && path.substr(path.size() - 5) == ".yaml") {
|
||||||
|
/* YAML 文件模式 */
|
||||||
|
services = registry::InitParser::parseYaml(path);
|
||||||
|
} else {
|
||||||
|
/* TXT 文件模式(向后兼容 init.txt) */
|
||||||
|
services = registry::InitParser::parseTxt(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (services.empty()) {
|
||||||
|
std::cerr << "parse_self_init_list: 没有可启动的服务" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string row = "";
|
for (const auto& svc : services) {
|
||||||
char ch;
|
/* 启动前等待(替代散落在 _run.sh 中的 sleep) */
|
||||||
while (file.get(ch))
|
if (svc.sleep_before > 0) {
|
||||||
|
std::cerr << "[pmc] " << svc.name
|
||||||
|
<< " 等待 " << svc.sleep_before << "s..." << std::endl;
|
||||||
|
std::this_thread::sleep_for(
|
||||||
|
std::chrono::seconds(svc.sleep_before));
|
||||||
|
}
|
||||||
|
|
||||||
if (ch == '\n') {
|
/* 设置环境变量 */
|
||||||
|
for (const auto& [k, v] : svc.env)
|
||||||
|
setenv(k.c_str(), v.c_str(), 1);
|
||||||
|
|
||||||
auto pos = row.find("#");
|
/* 清理已停止的进程,然后创建新进程 */
|
||||||
if (pos != -1)
|
|
||||||
row = row.substr(0, pos);
|
|
||||||
if (row != "") { /* trim() */
|
|
||||||
ppool.clr();
|
ppool.clr();
|
||||||
ppool.crtp(row); /* 创建进程 */
|
|
||||||
row = "";
|
std::string full_cmd = svc.toCommand();
|
||||||
|
std::cerr << "[pmc] 启动: " << svc.name
|
||||||
|
<< " -> " << full_cmd << std::endl;
|
||||||
|
ppool.crtp(full_cmd);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
else row += ch;
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (std::exception &exp) {
|
catch (std::exception &exp) {
|
||||||
std::cerr << "Exception at: parse_self_init_list()" << std::endl;
|
std::cerr << "Exception at: parse_self_init_list()" << std::endl;
|
||||||
std::cerr << "Exception type: " << typeid(exp).name() << std::endl;
|
std::cerr << "Exception type: " << typeid(exp).name() << std::endl;
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
#include "registry/InitParser.hh"
|
||||||
|
|
||||||
|
#include <yaml-cpp/yaml.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace qing::registry {
|
||||||
|
|
||||||
|
/* -------- ServiceConfig -------- */
|
||||||
|
|
||||||
|
std::string ServiceConfig::toCommand() const {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << cmd;
|
||||||
|
for (const auto& a : args) {
|
||||||
|
oss << ' ' << a;
|
||||||
|
}
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------- InitParser -------- */
|
||||||
|
|
||||||
|
std::vector<ServiceConfig> InitParser::load(const std::string& dir) {
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
auto yaml_path = fs::path(dir) / "services.yaml";
|
||||||
|
auto txt_path = fs::path(dir) / "init.txt";
|
||||||
|
|
||||||
|
/* 优先 services.yaml */
|
||||||
|
if (fs::exists(yaml_path)) {
|
||||||
|
std::cerr << "[InitParser] 使用 services.yaml: " << yaml_path << std::endl;
|
||||||
|
return parseYaml(yaml_path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 回退 init.txt */
|
||||||
|
if (fs::exists(txt_path)) {
|
||||||
|
std::cerr << "[InitParser] 回退 init.txt: " << txt_path << std::endl;
|
||||||
|
return parseTxt(txt_path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "[InitParser] 未找到 services.yaml 或 init.txt 于 " << dir << std::endl;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ServiceConfig> InitParser::parseYaml(const std::string& path) {
|
||||||
|
std::vector<ServiceConfig> result;
|
||||||
|
|
||||||
|
YAML::Node root;
|
||||||
|
try {
|
||||||
|
root = YAML::LoadFile(path);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "[InitParser] YAML 解析失败: " << e.what() << std::endl;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!root["services"] || !root["services"].IsSequence()) {
|
||||||
|
std::cerr << "[InitParser] services.yaml 缺少 services 序列" << std::endl;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& node : root["services"]) {
|
||||||
|
ServiceConfig svc;
|
||||||
|
|
||||||
|
if (node["name"])
|
||||||
|
svc.name = node["name"].as<std::string>();
|
||||||
|
|
||||||
|
if (node["cmd"])
|
||||||
|
svc.cmd = node["cmd"].as<std::string>();
|
||||||
|
|
||||||
|
if (node["args"] && node["args"].IsSequence())
|
||||||
|
for (const auto& a : node["args"])
|
||||||
|
svc.args.push_back(a.as<std::string>());
|
||||||
|
|
||||||
|
if (node["env"] && node["env"].IsMap())
|
||||||
|
for (const auto& kv : node["env"])
|
||||||
|
svc.env[kv.first.as<std::string>()] = kv.second.as<std::string>();
|
||||||
|
|
||||||
|
if (node["depends_on"] && node["depends_on"].IsSequence())
|
||||||
|
for (const auto& d : node["depends_on"])
|
||||||
|
svc.depends_on.push_back(d.as<std::string>());
|
||||||
|
|
||||||
|
if (node["sleep_before"])
|
||||||
|
svc.sleep_before = node["sleep_before"].as<int>(0);
|
||||||
|
|
||||||
|
if (svc.cmd.empty()) {
|
||||||
|
std::cerr << "[InitParser] 跳过缺少 cmd 的服务: " << svc.name << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push_back(std::move(svc));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "[InitParser] 解析完成,共 " << result.size() << " 个服务" << std::endl;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ServiceConfig> InitParser::parseTxt(const std::string& path) {
|
||||||
|
std::vector<ServiceConfig> result;
|
||||||
|
|
||||||
|
std::ifstream file(path);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
std::cerr << "[InitParser] 无法打开 init.txt: " << path << std::endl;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
/* 去除注释(# 之后的内容) */
|
||||||
|
auto pos = line.find('#');
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
line = line.substr(0, pos);
|
||||||
|
|
||||||
|
/* trim 空白 */
|
||||||
|
auto first = line.find_first_not_of(" \t\r\n");
|
||||||
|
if (first == std::string::npos)
|
||||||
|
continue; /* 空行 */
|
||||||
|
auto last = line.find_last_not_of(" \t\r\n");
|
||||||
|
line = line.substr(first, last - first + 1);
|
||||||
|
|
||||||
|
ServiceConfig svc;
|
||||||
|
svc.cmd = line;
|
||||||
|
/* init.txt 模式下 name/args/env/depends_on/sleep_before 均为空/默认 */
|
||||||
|
result.push_back(std::move(svc));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "[InitParser] init.txt 解析完成,共 " << result.size() << " 个服务" << std::endl;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace qing::registry
|
||||||
@@ -0,0 +1,806 @@
|
|||||||
|
# Core 启动配置 YAML 化与 CLI 参数标准化 · 开发文档
|
||||||
|
|
||||||
|
> 文档类型:功能开发计划
|
||||||
|
> 模块:core(PMC / Nidus)+ 全部子服务
|
||||||
|
> 作者:自动生成
|
||||||
|
> 日期:2026-08-10
|
||||||
|
> 前置关系:本文档是 `core_service_registry_dev_doc.md` P7 阶段(services.yaml)的前置拆分,聚焦"配置格式迁移 + 参数透传 + CLI 标准化"三步基础设施改造
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 概述
|
||||||
|
|
||||||
|
### 1.1 背景与动机
|
||||||
|
|
||||||
|
当前 core 通过 `init.txt`(纯命令列表)拉起 11 个子服务,存在以下问题:
|
||||||
|
|
||||||
|
| 现状 | 问题 |
|
||||||
|
|------|------|
|
||||||
|
| `init.txt` 每行一条 bash 命令,无结构化字段 | 无法为每个服务指定命令行参数、环境变量、依赖关系 |
|
||||||
|
| 5/11 个 `_run.sh` 不转发 `"$@"` | core 即便想传参也传不进去 |
|
||||||
|
| `sleep 2` 等依赖等待逻辑散落在各 `_run.sh` 中 | 无统一管理,调整需逐个脚本修改 |
|
||||||
|
| waf 的 `-c config.yaml` 硬编码在 `_run.sh` | 参数不可外部覆盖 |
|
||||||
|
| 各服务 CLI 接口不统一 | ca/gateway 仅有 `--help/--version`,waf 有 `-c/-list/-test/-check`,其余 8 个服务零 CLI 支持 |
|
||||||
|
|
||||||
|
**本方案目标**:通过三步改造,让 core 能够以结构化 YAML 声明每个服务的启动命令和参数,参数能透传到各服务二进制/脚本,并建立统一的 CLI 参数规范——为注册中心 `services.yaml` + `depends_on` DAG 拓扑排序打下基础。
|
||||||
|
|
||||||
|
### 1.2 设计目标
|
||||||
|
|
||||||
|
1. **结构化启动声明**:`init.txt` → `services.yaml`,每个服务可声明 `cmd`、`args`、`env`、`depends_on`、`sleep_before`
|
||||||
|
2. **参数透传**:全部 11 个 `_run.sh` 统一转发 `"$@"`,消除硬编码参数
|
||||||
|
3. **CLI 标准化**:定义通用参数约定(`--host`/`--port`/`--config`/`--log-level`/`--instance`),各服务逐步适配
|
||||||
|
4. **向后兼容**:`services.yaml` 不存在时回退 `init.txt`,现有部署零中断
|
||||||
|
5. **yaml-cpp 引入**:vendored 到 `core/third_party/yaml-cpp/`,不依赖系统包管理器
|
||||||
|
|
||||||
|
### 1.3 与注册中心计划的关系
|
||||||
|
|
||||||
|
```
|
||||||
|
本文档(三步改造) 注册中心计划(core_service_registry_dev_doc.md)
|
||||||
|
┌─────────────────────┐ ┌─────────────────────────────┐
|
||||||
|
│ Step 1: services.yaml│ ──────▶ │ P7: services.yaml DAG 排序 │
|
||||||
|
│ Step 2: _run.sh 透传 │ ──────▶ │ P2: init 解析后自动填充注册表 │
|
||||||
|
│ Step 3: CLI 标准化 │ ──────▶ │ P5: RegistrationClient SDK │
|
||||||
|
└─────────────────────┘ └─────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
本方案是注册中心的**基础设施前置**——做完这三步,P2/P5/P7 的工作量直接减半。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 现状分析
|
||||||
|
|
||||||
|
### 2.1 init.txt 当前内容
|
||||||
|
|
||||||
|
```
|
||||||
|
bash /opt/micro_servers/db2/_run.sh
|
||||||
|
bash /opt/micro_servers/ai_review/_run.sh
|
||||||
|
bash /opt/micro_servers/dnfs2/_run.sh
|
||||||
|
bash /opt/micro_servers/smtp/_run.sh
|
||||||
|
bash /opt/micro_servers/fsys/_run.sh
|
||||||
|
bash /opt/micro_servers/waf/_run.sh
|
||||||
|
bash /opt/micro_servers/ca/_run.sh
|
||||||
|
bash /opt/micro_servers/gateway/_run.sh
|
||||||
|
bash /opt/micro_servers/captcha2/_run.sh
|
||||||
|
bash /opt/micro_servers/aibox/_run.sh
|
||||||
|
bash /opt/micro_servers/redirect80/_run.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
纯命令列表,无参数、无元数据、无依赖声明。
|
||||||
|
|
||||||
|
### 2.2 各服务 _run.sh 现状
|
||||||
|
|
||||||
|
| 服务 | 语言 | `"$@"` 转发 | 硬编码参数 | 特殊处理 | sleep 等待 |
|
||||||
|
|------|------|-------------|-----------|----------|------------|
|
||||||
|
| db2 | C++ | ✅ `"$@"` | — | `set -e` | — |
|
||||||
|
| dnfs2 | C++ | ✅ `"$@"` | — | `set -e` | — |
|
||||||
|
| fsys | C++ | ✅ `"$@"` | — | `set -e` | — |
|
||||||
|
| ca | C++ | ✅ `"$@"` | — | — | `sleep 2` |
|
||||||
|
| gateway | C++ | ✅ `"$@"` | — | — | `sleep 2` |
|
||||||
|
| waf | Go | ❌ | `-c config.yaml` | — | — |
|
||||||
|
| captcha2 | C++ | ❌ | — | — | `sleep 1` |
|
||||||
|
| aibox | Python | ⚠️ `$@`(未加引号) | — | `_setenv.sh` + venv | — |
|
||||||
|
| ai_review | Python | ❌ | — | venv | — |
|
||||||
|
| smtp | Python | ❌ | — | venv | `sleep 2` |
|
||||||
|
| redirect80 | Python | ❌ | — | setcap + venv | — |
|
||||||
|
|
||||||
|
**统计**:5 个已转发、1 个半转发(未加引号)、5 个未转发。3 个脚本含 `sleep` 硬编码。
|
||||||
|
|
||||||
|
### 2.3 各服务 CLI 参数支持现状
|
||||||
|
|
||||||
|
| 服务 | 语言 | CLI 框架 | 实际参数 | 配置来源 |
|
||||||
|
|------|------|----------|----------|----------|
|
||||||
|
| db2 | C++ | 无 | 无 | 硬编码常量 |
|
||||||
|
| dnfs2 | C++ | 无 | 无 | 硬编码 + confs |
|
||||||
|
| fsys | C++ | 无 | 无 | 硬编码 |
|
||||||
|
| captcha2 | C++ | 无 | 无 | 硬编码 |
|
||||||
|
| ca | C++ | `boost::program_options` | `--help` `--version`(仅此) | confs (ca.ini) + 环境变量 |
|
||||||
|
| gateway | C++ | `boost::program_options` | `--help` `--version`(仅此) | confs (gateway.ini) + 环境变量 |
|
||||||
|
| waf | Go | `flag` | `-c` `-list` `-test` `-check` | YAML 配置文件 |
|
||||||
|
| aibox | Python | `argparse`(已 import 未使用) | 无 | `_setenv.sh` + 硬编码 |
|
||||||
|
| ai_review | Python | 无 | 无 | 硬编码 |
|
||||||
|
| smtp | Python | 无 | 无 | 硬编码 |
|
||||||
|
| redirect80 | Python | 无 | 无 | 硬编码 |
|
||||||
|
|
||||||
|
**关键发现**:
|
||||||
|
- ca 和 gateway 已引入 `boost::program_options` 但只实现了 `--help`/`--version`,实际配置全走 confs + 环境变量
|
||||||
|
- aibox 已 `import argparse` 但从未调用,是死代码
|
||||||
|
- waf 是唯一有完整 CLI 接口的服务(Go `flag` 包)
|
||||||
|
- 8/11 个服务零 CLI 参数支持
|
||||||
|
|
||||||
|
### 2.4 配置加载模式分类
|
||||||
|
|
||||||
|
当前各服务的配置获取有三种模式:
|
||||||
|
|
||||||
|
| 模式 | 服务 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| **confs + 环境变量** | ca, gateway, dnfs2 | 从 confs 服务拉取 ini 配置,环境变量可覆盖;`CONFS_HOST`/`CONFS_PORT` 引导 |
|
||||||
|
| **本地配置文件** | waf | `-c config.yaml` 指定 YAML 配置 |
|
||||||
|
| **硬编码** | db2, fsys, captcha2, aibox, ai_review, smtp, redirect80 | 常量直接写在源码中 |
|
||||||
|
|
||||||
|
CLI 标准化后,三种模式可统一为:**CLI 参数(最高优先级)> 环境变量 > confs/配置文件 > 硬编码默认值**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 三步改造方案
|
||||||
|
|
||||||
|
### 3.1 总览
|
||||||
|
|
||||||
|
```
|
||||||
|
Step 1: init.txt → services.yaml Step 2: _run.sh 参数透传 Step 3: CLI 参数标准化
|
||||||
|
┌──────────────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
|
||||||
|
│ • 引入 yaml-cpp (vendored) │ │ • 11 个 _run.sh 统一 │ │ • 定义通用参数约定 │
|
||||||
|
│ • 设计 services.yaml 格式 │ ──▶ │ 末尾 exec 加 "$@" │ ──▶ │ • _run.sh 注入默认值 │
|
||||||
|
│ • core 解析 YAML 并启动 │ │ • 移除硬编码参数 │ │ • 各服务逐步适配 │
|
||||||
|
│ • 回退兼容 init.txt │ │ • sleep 移至 YAML │ │ • 环境变量桥接 │
|
||||||
|
└──────────────────────────────┘ └──────────────────────┘ └──────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Step 1:init.txt → services.yaml
|
||||||
|
|
||||||
|
### 4.1 yaml-cpp 引入
|
||||||
|
|
||||||
|
采用系统包安装方式(已写入 `_setup.deb.sh` 和 `_setup.rhel.sh`):
|
||||||
|
|
||||||
|
| 发行版 | 包名 | 安装命令 |
|
||||||
|
|--------|------|----------|
|
||||||
|
| Debian/Ubuntu | `libyaml-cpp-dev` | `apt install libyaml-cpp-dev` |
|
||||||
|
| RHEL/CentOS/Rocky | `yaml-cpp-devel` | `dnf install yaml-cpp-devel` |
|
||||||
|
|
||||||
|
**Makefile 集成**(已完成):
|
||||||
|
|
||||||
|
```makefile
|
||||||
|
# 链接 yaml-cpp 系统库
|
||||||
|
LIBS := ... -lyaml-cpp
|
||||||
|
|
||||||
|
# InitParser 编译目标
|
||||||
|
$(BUILD_DIR)/InitParser.o: src/registry/InitParser.cpp
|
||||||
|
$(CPP) $(CPPFLAGS) -c $^ $(INCS) -o $@
|
||||||
|
|
||||||
|
# 链接时追加
|
||||||
|
$(APP_NAME).out: ... $(BUILD_DIR)/InitParser.o
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 services.yaml 格式设计
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# core/services.yaml
|
||||||
|
# 声明式服务启动配置(替代 init.txt)
|
||||||
|
# 如果本文件存在则优先使用,否则回退 init.txt
|
||||||
|
|
||||||
|
services:
|
||||||
|
# --- 数据层 ---
|
||||||
|
- name: db2
|
||||||
|
cmd: bash /opt/micro_servers/db2/_run.sh
|
||||||
|
args: []
|
||||||
|
env: {}
|
||||||
|
depends_on: []
|
||||||
|
sleep_before: 0
|
||||||
|
|
||||||
|
# --- AI 服务 ---
|
||||||
|
- name: ai_review
|
||||||
|
cmd: bash /opt/micro_servers/ai_review/_run.sh
|
||||||
|
args: ["--port", "8007", "--log-level", "info"]
|
||||||
|
env:
|
||||||
|
PYTHONUNBUFFERED: "1"
|
||||||
|
depends_on: [db2]
|
||||||
|
sleep_before: 2
|
||||||
|
|
||||||
|
# --- 文件服务 ---
|
||||||
|
- name: dnfs2
|
||||||
|
cmd: bash /opt/micro_servers/dnfs2/_run.sh
|
||||||
|
args: []
|
||||||
|
env: {}
|
||||||
|
depends_on: [db2, ai_review]
|
||||||
|
sleep_before: 0
|
||||||
|
|
||||||
|
# --- 邮件服务 ---
|
||||||
|
- name: smtp
|
||||||
|
cmd: bash /opt/micro_servers/smtp/_run.sh
|
||||||
|
args: []
|
||||||
|
env: {}
|
||||||
|
depends_on: []
|
||||||
|
sleep_before: 2
|
||||||
|
|
||||||
|
# --- 前端静态资源 ---
|
||||||
|
- name: fsys
|
||||||
|
cmd: bash /opt/micro_servers/fsys/_run.sh
|
||||||
|
args: []
|
||||||
|
env: {}
|
||||||
|
depends_on: []
|
||||||
|
sleep_before: 0
|
||||||
|
|
||||||
|
# --- 安全链路 ---
|
||||||
|
- name: waf
|
||||||
|
cmd: bash /opt/micro_servers/waf/_run.sh
|
||||||
|
args: ["-c", "config.yaml"]
|
||||||
|
env: {}
|
||||||
|
depends_on: [ca, gateway]
|
||||||
|
sleep_before: 0
|
||||||
|
|
||||||
|
- name: ca
|
||||||
|
cmd: bash /opt/micro_servers/ca/_run.sh
|
||||||
|
args: []
|
||||||
|
env: {}
|
||||||
|
depends_on: [db2]
|
||||||
|
sleep_before: 2
|
||||||
|
|
||||||
|
- name: gateway
|
||||||
|
cmd: bash /opt/micro_servers/gateway/_run.sh
|
||||||
|
args: []
|
||||||
|
env: {}
|
||||||
|
depends_on: [db2]
|
||||||
|
sleep_before: 2
|
||||||
|
|
||||||
|
# --- 验证码 ---
|
||||||
|
- name: captcha2
|
||||||
|
cmd: bash /opt/micro_servers/captcha2/_run.sh
|
||||||
|
args: []
|
||||||
|
env: {}
|
||||||
|
depends_on: []
|
||||||
|
sleep_before: 1
|
||||||
|
|
||||||
|
# --- AI 工具箱 ---
|
||||||
|
- name: aibox
|
||||||
|
cmd: bash /opt/micro_servers/aibox/_run.sh
|
||||||
|
args: []
|
||||||
|
env:
|
||||||
|
PATH: "${PATH}:~/.aibox/skills"
|
||||||
|
depends_on: []
|
||||||
|
sleep_before: 0
|
||||||
|
|
||||||
|
# --- 端口重定向 ---
|
||||||
|
- name: redirect80
|
||||||
|
cmd: bash /opt/micro_servers/redirect80/_run.sh
|
||||||
|
args: []
|
||||||
|
env: {}
|
||||||
|
depends_on: [waf]
|
||||||
|
sleep_before: 0
|
||||||
|
```
|
||||||
|
|
||||||
|
**字段说明**:
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| `name` | string | 是 | 服务唯一标识,用于日志和未来注册表 |
|
||||||
|
| `cmd` | string | 是 | 启动命令(与 init.txt 每行格式一致) |
|
||||||
|
| `args` | string[] | 否 | 传递给 `_run.sh` 的命令行参数列表 |
|
||||||
|
| `env` | map<string,string> | 否 | 启动前设置的环境变量 |
|
||||||
|
| `depends_on` | string[] | 否 | 依赖的服务名列表(未来 DAG 排序用,当前仅记录) |
|
||||||
|
| `sleep_before` | int | 否 | 启动前等待秒数(替代散落在 _run.sh 中的 sleep) |
|
||||||
|
|
||||||
|
### 4.3 core 解析逻辑
|
||||||
|
|
||||||
|
新增 `include/registry/InitParser.hh` + `src/registry/InitParser.cpp`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// include/registry/InitParser.hh
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace qing::registry {
|
||||||
|
|
||||||
|
struct ServiceConfig {
|
||||||
|
std::string name;
|
||||||
|
std::string cmd;
|
||||||
|
std::vector<std::string> args;
|
||||||
|
std::map<std::string, std::string> env;
|
||||||
|
std::vector<std::string> depends_on;
|
||||||
|
int sleep_before = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InitParser {
|
||||||
|
public:
|
||||||
|
// 优先读 services.yaml,不存在则回退 init.txt
|
||||||
|
static std::vector<ServiceConfig> load(const std::string& conf_dir);
|
||||||
|
|
||||||
|
// 解析 services.yaml
|
||||||
|
static std::vector<ServiceConfig> parseYaml(const std::string& path);
|
||||||
|
|
||||||
|
// 解析 init.txt(向后兼容)
|
||||||
|
static std::vector<ServiceConfig> parseTxt(const std::string& path);
|
||||||
|
|
||||||
|
// 将 ServiceConfig 拼成完整命令字符串(cmd + " " + args.join(" "))
|
||||||
|
static std::string toCommand(const ServiceConfig& svc);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace qing::registry
|
||||||
|
```
|
||||||
|
|
||||||
|
**解析流程**:
|
||||||
|
|
||||||
|
```
|
||||||
|
load(conf_dir):
|
||||||
|
1. 检查 conf_dir/services.yaml 是否存在
|
||||||
|
2. 存在 → parseYaml() → 返回 ServiceConfig 列表
|
||||||
|
3. 不存在 → 检查 conf_dir/init.txt
|
||||||
|
4. 存在 → parseTxt() → 每行作为 ServiceConfig{name="", cmd=line, args=[]}
|
||||||
|
5. 都不存在 → 报错退出
|
||||||
|
```
|
||||||
|
|
||||||
|
**parseYaml 核心逻辑**(使用 yaml-cpp):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
|
std::vector<ServiceConfig> InitParser::parseYaml(const std::string& path) {
|
||||||
|
YAML::Node root = YAML::LoadFile(path);
|
||||||
|
std::vector<ServiceConfig> result;
|
||||||
|
|
||||||
|
for (const auto& node : root["services"]) {
|
||||||
|
ServiceConfig svc;
|
||||||
|
svc.name = node["name"].as<std::string>("");
|
||||||
|
svc.cmd = node["cmd"].as<std::string>();
|
||||||
|
|
||||||
|
if (node["args"])
|
||||||
|
for (const auto& a : node["args"])
|
||||||
|
svc.args.push_back(a.as<std::string>());
|
||||||
|
|
||||||
|
if (node["env"])
|
||||||
|
for (const auto& kv : node["env"])
|
||||||
|
svc.env[kv.first.as<std::string>()] = kv.second.as<std::string>();
|
||||||
|
|
||||||
|
if (node["depends_on"])
|
||||||
|
for (const auto& d : node["depends_on"])
|
||||||
|
svc.depends_on.push_back(d.as<std::string>());
|
||||||
|
|
||||||
|
if (node["sleep_before"])
|
||||||
|
svc.sleep_before = node["sleep_before"].as<int>(0);
|
||||||
|
|
||||||
|
result.push_back(std::move(svc));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**启动执行逻辑**(改动 `pmc_mtd::parse_self_init_list`):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// pmc_mtd.cpp 中改造
|
||||||
|
void pmc_mtd::init_from_config(const std::string& conf_dir) {
|
||||||
|
auto services = InitParser::load(conf_dir);
|
||||||
|
|
||||||
|
for (const auto& svc : services) {
|
||||||
|
// 1. sleep_before 等待
|
||||||
|
if (svc.sleep_before > 0)
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(svc.sleep_before));
|
||||||
|
|
||||||
|
// 2. 设置环境变量
|
||||||
|
for (const auto& [k, v] : svc.env)
|
||||||
|
setenv(k.c_str(), v.c_str(), 1);
|
||||||
|
|
||||||
|
// 3. 拼接完整命令并启动
|
||||||
|
std::string full_cmd = InitParser::toCommand(svc);
|
||||||
|
// full_cmd = "bash /opt/micro_servers/db2/_run.sh --port 8007 --log-level info"
|
||||||
|
ppool.crtp(full_cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4 向后兼容策略
|
||||||
|
|
||||||
|
```
|
||||||
|
services.yaml 存在?
|
||||||
|
│
|
||||||
|
┌─── 是 ──┤── 否 ───┐
|
||||||
|
▼ ▼
|
||||||
|
parseYaml() init.txt 存在?
|
||||||
|
│ │
|
||||||
|
│ ┌── 是 ──┤── 否 ───┐
|
||||||
|
│ ▼ ▼
|
||||||
|
│ parseTxt() 报错退出
|
||||||
|
│ │
|
||||||
|
└─────┬─────┘
|
||||||
|
▼
|
||||||
|
ServiceConfig[]
|
||||||
|
逐个启动
|
||||||
|
```
|
||||||
|
|
||||||
|
- `init.txt` 模式下,每行解析为 `{name="", cmd=line, args=[], sleep_before=0}`,行为与当前完全一致
|
||||||
|
- `services.yaml` 模式下,享受参数透传和 sleep 管理能力
|
||||||
|
- Makefile 的 `CONF_NAME` 可逐步从 `init.txt` 切换为 `services.yaml`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Step 2:_run.sh 参数透传
|
||||||
|
|
||||||
|
### 5.1 改造规则
|
||||||
|
|
||||||
|
每个 `_run.sh` 的末尾 `exec` 行必须带 `"$@"`,同时移除硬编码参数和散落的 `sleep`。
|
||||||
|
|
||||||
|
**改造模板**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# <service>/_run.sh — 标准化启动脚本
|
||||||
|
cd "$(dirname "$0")" || exit
|
||||||
|
|
||||||
|
# --- 服务特有前置(venv / setcap 等)保持不变 ---
|
||||||
|
|
||||||
|
# 启动:"$@" 透传 core/services.yaml 传入的参数
|
||||||
|
exec <binary_or_python> "$@"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 逐服务改造清单
|
||||||
|
|
||||||
|
| 服务 | 当前 exec 行 | 改造后 | 额外改动 |
|
||||||
|
|------|-------------|--------|----------|
|
||||||
|
| db2 | `exec ./build/db2 "$@"` | ✅ 无需改 | — |
|
||||||
|
| dnfs2 | `exec ./build/dnfs2 "$@"` | ✅ 无需改 | — |
|
||||||
|
| fsys | `exec ./build/fsys "$@"` | ✅ 无需改 | — |
|
||||||
|
| ca | `exec ./build/ca.out "$@"` | ✅ 无需改 | 移除 `sleep 2`(移交 YAML) |
|
||||||
|
| gateway | `exec ./build/gateway.out "$@"` | ✅ 无需改 | 移除 `sleep 2`(移交 YAML) |
|
||||||
|
| waf | `exec ./waf.bin -c config.yaml` | `exec ./waf.bin -c config.yaml "$@"` | 保留 `-c config.yaml` 作为脚本默认值,services.yaml `args: []` |
|
||||||
|
| captcha2 | `exec ./captcha2.bin` | `exec ./captcha2.bin "$@"` | 移除 `sleep 1`(移交 YAML) |
|
||||||
|
| aibox | `exec python aibox.py $@` | `exec python aibox.py "$@"` | `$@` → `"$@"` 加引号 |
|
||||||
|
| ai_review | `exec python3 ai_review.py` | `exec python3 ai_review.py "$@"` | — |
|
||||||
|
| smtp | `exec python3 smtp_v2.py` | `exec python3 smtp_v2.py "$@"` | 移除 `sleep 2`(移交 YAML) |
|
||||||
|
| redirect80 | `exec python3 redirect80.py` | `exec python3 redirect80.py "$@"` | — |
|
||||||
|
|
||||||
|
**统计**:6 个无需改、5 个需改 exec 行、4 个需移除 sleep。
|
||||||
|
|
||||||
|
### 5.3 sleep 迁移对照
|
||||||
|
|
||||||
|
| 服务 | 当前 sleep 位置 | 迁移到 services.yaml |
|
||||||
|
|------|----------------|---------------------|
|
||||||
|
| ca | `_run.sh` 中 `sleep 2` | `sleep_before: 2` |
|
||||||
|
| gateway | `_run.sh` 中 `sleep 2` | `sleep_before: 2` |
|
||||||
|
| captcha2 | `_run.sh` 中 `sleep 1` | `sleep_before: 1` |
|
||||||
|
| smtp | `_run.sh` 中 `sleep 2` | `sleep_before: 2` |
|
||||||
|
|
||||||
|
移除后 `_run.sh` 只负责"切换目录 + 前置准备 + exec",不负责时序控制。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Step 3:CLI 参数标准化
|
||||||
|
|
||||||
|
### 6.1 通用参数约定
|
||||||
|
|
||||||
|
定义一组所有服务都应支持的通用 CLI 参数:
|
||||||
|
|
||||||
|
| 参数 | 短选项 | 类型 | 默认值 | 说明 |
|
||||||
|
|------|--------|------|--------|------|
|
||||||
|
| `--host` | `-H` | string | `127.0.0.1` | 绑定地址 |
|
||||||
|
| `--port` | `-p` | int | 服务特定 | 监听端口 |
|
||||||
|
| `--config` | `-c` | string | 服务特定 | 配置文件路径 |
|
||||||
|
| `--log-level` | `-l` | enum | `info` | `debug\|info\|warn\|error` |
|
||||||
|
| `--instance` | `-i` | string | 服务名 | 实例标识(未来多实例/注册中心用) |
|
||||||
|
| `--help` | `-h` | flag | — | 输出帮助 |
|
||||||
|
| `--version` | `-v` | flag | — | 输出版本 |
|
||||||
|
|
||||||
|
**优先级规则**:`CLI 参数 > 环境变量 > confs/配置文件 > 硬编码默认值`
|
||||||
|
|
||||||
|
### 6.2 _run.sh 默认值注入
|
||||||
|
|
||||||
|
在服务二进制还不支持所有参数的过渡期,`_run.sh` 可注入默认值:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# waf/_run.sh — 标准化后
|
||||||
|
cd "$(dirname "$0")" || exit
|
||||||
|
|
||||||
|
# 默认参数(可被 services.yaml args 覆盖)
|
||||||
|
DEFAULT_ARGS=(-c config.yaml)
|
||||||
|
|
||||||
|
exec ./waf.bin "${DEFAULT_ARGS[@]}" "$@"
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# db2/_run.sh — 标准化后
|
||||||
|
cd "$(dirname "$0")" || exit
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# 默认参数
|
||||||
|
DEFAULT_ARGS=(--host 127.0.0.1 --port 8005 --log-level info)
|
||||||
|
|
||||||
|
exec ./build/db2 "${DEFAULT_ARGS[@]}" "$@"
|
||||||
|
```
|
||||||
|
|
||||||
|
**原理**:`"$@"` 追加在 `DEFAULT_ARGS` 之后,如果用户通过 services.yaml 传了同名参数,取决于各服务的解析逻辑(`boost::program_options` 默认后者覆盖前者;Python `argparse` 同理)。
|
||||||
|
|
||||||
|
### 6.3 各语言适配指南
|
||||||
|
|
||||||
|
#### C++ 服务(db2, dnfs2, fsys, captcha2)
|
||||||
|
|
||||||
|
当前这 4 个服务无 CLI 框架。建议引入 `boost::program_options`(ca/gateway 已有先例):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// db2/src/db2.cpp — 新增 CLI 解析
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
po::options_description desc("db2 — database RPC service");
|
||||||
|
desc.add_options()
|
||||||
|
("help,h", "output help message")
|
||||||
|
("version,v", "output version message")
|
||||||
|
("host,H", po::value<std::string>()->default_value("127.0.0.1"), "bind address")
|
||||||
|
("port,p", po::value<int>()->default_value(8005), "listen port")
|
||||||
|
("log-level,l", po::value<std::string>()->default_value("info"),
|
||||||
|
"debug|info|warn|error")
|
||||||
|
("instance,i", po::value<std::string>()->default_value("db2"), "instance name")
|
||||||
|
;
|
||||||
|
|
||||||
|
po::variables_map vm;
|
||||||
|
try {
|
||||||
|
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||||
|
po::notify(vm);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||||
|
std::cerr << desc << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("help")) { std::cout << desc << std::endl; return 0; }
|
||||||
|
if (vm.count("version")) { std::cout << "db2 1.0.0" << std::endl; return 0; }
|
||||||
|
|
||||||
|
std::string host = vm["host"].as<std::string>();
|
||||||
|
int port = vm["port"].as<int>();
|
||||||
|
std::string log_level = vm["log-level"].as<std::string>();
|
||||||
|
|
||||||
|
// 后续使用 host/port/log_level 启动服务...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### C++ 服务(ca, gateway)— 扩展现有 program_options
|
||||||
|
|
||||||
|
ca 和 gateway已有 `po::options_description` 但只注册了 `--help`/`--version`,需追加通用参数:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// ca/src/main.cpp — 扩展
|
||||||
|
desc.add_options()
|
||||||
|
("help,h", "output help message")
|
||||||
|
("version,v", "output version message")
|
||||||
|
// 新增通用参数
|
||||||
|
("host,H", po::value<std::string>()->default_value("127.0.0.1"), "bind address")
|
||||||
|
("port,p", po::value<int>()->default_value(8443), "listen port")
|
||||||
|
("log-level,l", po::value<std::string>()->default_value("info"),
|
||||||
|
"debug|info|warn|error")
|
||||||
|
("instance,i", po::value<std::string>()->default_value("ca"), "instance name")
|
||||||
|
;
|
||||||
|
```
|
||||||
|
|
||||||
|
注意:ca/gateway 当前配置走 confs + 环境变量,CLI 参数应作为**覆盖层**,不替换 confs 机制。
|
||||||
|
|
||||||
|
#### Go 服务(waf)— 扩展现有 flag
|
||||||
|
|
||||||
|
waf 已有 `flag` 包,追加通用参数:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
var (
|
||||||
|
configFile = flag.String("c", "config.yaml", "配置文件路径")
|
||||||
|
host = flag.String("H", "127.0.0.1", "绑定地址")
|
||||||
|
port = flag.Int("p", 443, "监听端口")
|
||||||
|
logLevel = flag.String("l", "info", "debug|info|warn|error")
|
||||||
|
instance = flag.String("i", "waf", "实例名")
|
||||||
|
doList = flag.Bool("list", false, "列出所有规则后退出")
|
||||||
|
doTest = flag.String("test", "", "校验单个规则文件语法后退出")
|
||||||
|
doCheck = flag.String("check", "", "用当前规则测试输入字符串后退出")
|
||||||
|
)
|
||||||
|
flag.Parse()
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
注意:Go `flag` 包不支持短选项连写(`-H 127.0.0.1`),与 C++ `program_options` 的 `-H` 语法兼容。
|
||||||
|
|
||||||
|
#### Python 服务(aibox, ai_review, smtp, redirect80)
|
||||||
|
|
||||||
|
建议统一使用 `argparse`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""ai_review — AI 审核服务"""
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
parser = argparse.ArgumentParser(description="ai_review — AI 审核服务")
|
||||||
|
parser.add_argument("-H", "--host", default="127.0.0.1", help="绑定地址")
|
||||||
|
parser.add_argument("-p", "--port", type=int, default=8007, help="监听端口")
|
||||||
|
parser.add_argument("-l", "--log-level", default="info",
|
||||||
|
choices=["debug", "info", "warn", "error"], help="日志级别")
|
||||||
|
parser.add_argument("-i", "--instance", default="ai_review", help="实例名")
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
args = parse_args()
|
||||||
|
# 后续使用 args.host, args.port, args.log_level...
|
||||||
|
```
|
||||||
|
|
||||||
|
aibox 已有 `import argparse`(死代码),激活即可。
|
||||||
|
|
||||||
|
### 6.4 环境变量桥接
|
||||||
|
|
||||||
|
对于走 confs + 环境变量的服务(ca, gateway, dnfs2),CLI 参数应映射到环境变量,保持与现有 confs 机制兼容:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ca/_run.sh — 环境变量桥接模式
|
||||||
|
cd "$(dirname "$0")" || exit
|
||||||
|
|
||||||
|
# 从命令行参数提取并导出环境变量(供 confs 加载逻辑使用)
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-H|--host) export CA_HOST="$2"; shift 2 ;;
|
||||||
|
-p|--port) export CA_PORT="$2"; shift 2 ;;
|
||||||
|
-l|--log-level) export LOG_LEVEL="$2"; shift 2 ;;
|
||||||
|
*) EXTRA_ARGS+=("$1"); shift ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
exec ./build/ca.out "${EXTRA_ARGS[@]}"
|
||||||
|
```
|
||||||
|
|
||||||
|
这种桥接方式不需要立刻改 ca 的 C++ 源码——`_run.sh` 先把 CLI 参数翻译成环境变量,ca 现有的环境变量读取逻辑自然生效。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 实施计划
|
||||||
|
|
||||||
|
### 7.1 分步交付
|
||||||
|
|
||||||
|
| 步骤 | 改动范围 | 涉及文件 | 预估工时 | 风险 |
|
||||||
|
|------|----------|----------|----------|------|
|
||||||
|
| **S1-a** | yaml-cpp vendored + Makefile 集成 | `core/third_party/yaml-cpp/`、`core/Makefile` | 1h | 低 |
|
||||||
|
| **S1-b** | InitParser 实现 | `core/include/registry/InitParser.hh`、`core/src/registry/InitParser.cpp` | 2h | 低 |
|
||||||
|
| **S1-c** | pmc_mtd 改造(调用 InitParser) | `core/src/main/pmc_mtd.cpp` | 1h | 中(改核心启动路径) |
|
||||||
|
| **S1-d** | 创建 services.yaml | `core/services.yaml` | 0.5h | 低 |
|
||||||
|
| **S1-e** | 回退测试(删除 services.yaml 验证 init.txt 兼容) | — | 0.5h | 低 |
|
||||||
|
| **S2-a** | 5 个 _run.sh 改 exec 行 | `waf/`、`captcha2/`、`aibox/`、`ai_review/`、`smtp/`、`redirect80/` 的 `_run.sh` | 0.5h | 极低 |
|
||||||
|
| **S2-b** | 4 个 _run.sh 移除 sleep | `ca/`、`gateway/`、`captcha2/`、`smtp/` 的 `_run.sh` | 0.2h | 低(sleep 已移交 YAML) |
|
||||||
|
| **S3-a** | 定义 CLI 标准文档(本文档 §6) | — | 0h(已完成) | — |
|
||||||
|
| **S3-b** | C++ 服务适配(ca/gateway 扩展,db2/dnfs2/fsys/captcha2 新增) | 各服务 `src/*.cpp` | 4h | 中 |
|
||||||
|
| **S3-c** | Python 服务适配(argparse) | `aibox.py`、`ai_review.py`、`smtp_v2.py`、`redirect80.py` | 2h | 低 |
|
||||||
|
| **S3-d** | Go 服务适配(waf flag 扩展) | `waf/waf.go` | 0.5h | 低 |
|
||||||
|
| **S3-e** | _run.sh 默认值注入 | 各服务 `_run.sh` | 0.5h | 低 |
|
||||||
|
| **S4** | 端到端测试 | — | 1h | — |
|
||||||
|
|
||||||
|
**总计预估:~14 小时**
|
||||||
|
|
||||||
|
### 7.2 推荐实施顺序
|
||||||
|
|
||||||
|
```
|
||||||
|
S1-a (yaml-cpp 集成)
|
||||||
|
└─▶ S1-b (InitParser)
|
||||||
|
└─▶ S1-c (pmc_mtd 改造)
|
||||||
|
└─▶ S1-d (services.yaml)
|
||||||
|
└─▶ S1-e (回退测试) ──▶ Step 1 完成
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
S2-a + S2-b ( _run.sh 改造) ──▶ Step 2 完成
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
S3-b/c/d (各服务 CLI 适配)
|
||||||
|
└─▶ S3-e (默认值注入) ──▶ Step 3 完成
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
S4 (端到端测试)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.3 新增/改动文件清单
|
||||||
|
|
||||||
|
```
|
||||||
|
core/
|
||||||
|
├── include/registry/
|
||||||
|
│ └── InitParser.hh # 【新增】YAML/TXT 解析器头文件
|
||||||
|
├── src/registry/
|
||||||
|
│ └── InitParser.cpp # 【新增】YAML/TXT 解析器实现
|
||||||
|
├── src/main/pmc_mtd.cpp # 【改动】调用 InitParser 替代 parse_self_init_list
|
||||||
|
├── src/main.cpp # 【改动】--init 帮助文本更新
|
||||||
|
├── Makefile # 【改动】追加 InitParser.o 编译目标 + -lyaml-cpp 链接
|
||||||
|
├── _run.sh # 【改动】-i init.txt → -i .(目录模式自动查找)
|
||||||
|
├── services.yaml # 【新增】声明式服务启动配置
|
||||||
|
└── init.txt # 【保留】向后兼容回退
|
||||||
|
|
||||||
|
项目根目录/
|
||||||
|
├── _setup.deb.sh # 【改动】追加 libyaml-cpp-dev
|
||||||
|
└── _setup.rhel.sh # 【改动】追加 yaml-cpp-devel
|
||||||
|
|
||||||
|
各服务 _run.sh(11 个) # 【已完成】Step 2 统一 "$@" 透传 + 移除 sleep
|
||||||
|
|
||||||
|
C++ 服务源码(6 个) # 【待改】Step 3 新增/扩展 program_options
|
||||||
|
Python 服务源码(4 个) # 【待改】Step 3 新增 argparse
|
||||||
|
Go 服务源码(1 个) # 【待改】Step 3 扩展 flag
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 验证清单
|
||||||
|
|
||||||
|
### 8.1 Step 1 验证
|
||||||
|
|
||||||
|
- [ ] `make` 编译成功,yaml-cpp 源文件正确编译链接
|
||||||
|
- [ ] `services.yaml` 存在时,core 按 YAML 声明启动全部 11 个服务
|
||||||
|
- [ ] `services.yaml` 不存在时,core 回退 `init.txt`,行为与改造前完全一致
|
||||||
|
- [ ] `args` 字段的参数正确透传到 `_run.sh`
|
||||||
|
- [ ] `env` 字段的环境变量在子进程启动前生效
|
||||||
|
- [ ] `sleep_before` 字段正确控制启动间隔
|
||||||
|
|
||||||
|
### 8.2 Step 2 验证
|
||||||
|
|
||||||
|
- [x] 全部 11 个 `_run.sh` 末尾 `exec` 行带 `"$@"`
|
||||||
|
- [x] waf 保留 `-c config.yaml` 作为脚本默认值,追加 `"$@"` 透传,services.yaml `args: []`
|
||||||
|
- [x] aibox 的 `$@` 改为 `"$@"`(加引号,防空格路径问题)
|
||||||
|
- [x] ca/gateway/captcha2/smtp 的 `sleep` 从 `_run.sh` 移除,由 `services.yaml` 的 `sleep_before` 管理
|
||||||
|
- [ ] 手动执行 `_run.sh --help` 能透传到二进制(依赖 Step 3 CLI 适配)
|
||||||
|
|
||||||
|
### 8.3 Step 3 验证
|
||||||
|
|
||||||
|
- [ ] 全部服务支持 `--help` 输出用法
|
||||||
|
- [ ] 全部服务支持 `--version` 输出版本
|
||||||
|
- [ ] `--port` 能覆盖默认端口并生效
|
||||||
|
- [ ] `--log-level` 能控制日志输出级别
|
||||||
|
- [ ] `_run.sh` 默认值注入 + `services.yaml` 覆盖,两者叠加不冲突
|
||||||
|
- [ ] ca/gateway 的环境变量桥接模式正确工作
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 风险与缓解
|
||||||
|
|
||||||
|
| 风险 | 影响 | 缓解措施 |
|
||||||
|
|------|------|----------|
|
||||||
|
| yaml-cpp 编译增加构建时间 | 低(~10s) | 可接受;如需优化可预编译为静态库 |
|
||||||
|
| pmc_mtd 改造影响核心启动路径 | 高 | 保留 `init.txt` 回退路径;先在测试环境验证 |
|
||||||
|
| _run.sh 移除 sleep 后启动时序变化 | 中 | `services.yaml` 的 `sleep_before` 提供等价等待 |
|
||||||
|
| 各服务 CLI 参数适配工作量大 | 中 | 分批适配;_run.sh 默认值注入可过渡 |
|
||||||
|
| Go flag 与 C++ program_options 语法差异 | 低 | 两者都支持 `-H value` 和 `--host value` 格式 |
|
||||||
|
| Python argparse 与 C++ program_options 行为差异 | 低 | 测试覆盖;argparse 默认不覆盖已设默认值 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 附录
|
||||||
|
|
||||||
|
### A. 各服务端口与配置对照
|
||||||
|
|
||||||
|
| 服务 | 端口 | 协议 | 配置来源 | CLI 框架现状 |
|
||||||
|
|------|------|------|----------|-------------|
|
||||||
|
| db2 | 8005 | pymsg | 硬编码 | 无 |
|
||||||
|
| ai_review | 8007 | http | 硬编码 | 无 |
|
||||||
|
| dnfs2 | 8006 | http | 硬编码 + confs | 无 |
|
||||||
|
| smtp | 8008 | pymsg | 硬编码 | 无 |
|
||||||
|
| fsys | 8090 | http | 硬编码 | 无 |
|
||||||
|
| waf | 443 | https | YAML 配置文件 | Go flag ✅ |
|
||||||
|
| ca | 8443 | https | confs + 环境变量 | program_options(仅 --help/--version) |
|
||||||
|
| gateway | 8445 | http | confs + 环境变量 | program_options(仅 --help/--version) |
|
||||||
|
| captcha2 | 8009 | pymsg | 硬编码 | 无 |
|
||||||
|
| aibox | 8765 | websocket | _setenv.sh + 硬编码 | argparse(已 import 未使用) |
|
||||||
|
| redirect80 | 80 | http | 硬编码 | 无 |
|
||||||
|
|
||||||
|
### B. yaml-cpp 集成验证
|
||||||
|
|
||||||
|
已采用系统包方式(非 vendored),在 `_setup.deb.sh` / `_setup.rhel.sh` 中声明依赖:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Debian/Ubuntu
|
||||||
|
sudo apt install libyaml-cpp-dev
|
||||||
|
|
||||||
|
# RHEL/CentOS
|
||||||
|
sudo dnf install yaml-cpp-devel
|
||||||
|
```
|
||||||
|
|
||||||
|
Makefile 中 `-lyaml-cpp` 链接,`InitParser.cpp` 中 `#include <yaml-cpp/yaml.h>` 引用。
|
||||||
|
|
||||||
|
### C. 环境变量约定(现有 + 新增)
|
||||||
|
|
||||||
|
| 环境变量 | 使用方 | 当前/新增 | 说明 |
|
||||||
|
|----------|--------|-----------|------|
|
||||||
|
| `CONFS_HOST` | ca, gateway, dnfs2 | 现有 | confs 服务地址,默认 `127.0.0.1` |
|
||||||
|
| `CONFS_PORT` | ca, gateway, dnfs2 | 现有 | confs 服务端口,默认 `8010` |
|
||||||
|
| `CORE_HOST` | 未来 RegistrationClient | 新增 | core 注册中心地址,默认 `127.0.0.1` |
|
||||||
|
| `CORE_PORT` | 未来 RegistrationClient | 新增 | core 注册中心端口,默认 `5200` |
|
||||||
|
| `LOG_LEVEL` | 全部服务(可选) | 新增 | 日志级别,可被 `--log-level` 覆盖 |
|
||||||
|
|
||||||
|
### D. 与注册中心计划的衔接点
|
||||||
|
|
||||||
|
| 本方案产出 | 注册中心计划消费点 |
|
||||||
|
|-----------|-------------------|
|
||||||
|
| `services.yaml` 格式 | P7 直接复用,追加 `health_endpoint`/`protocol`/`restart_max` 等字段 |
|
||||||
|
| `InitParser` 解析器 | P2 调用 `parseYaml()` 后自动填充 `ServiceRegistry` |
|
||||||
|
| `ServiceConfig.depends_on` | P7 DAG 拓扑排序的输入 |
|
||||||
|
| `ServiceConfig.args` | 各服务通过 CLI 参数接收注册中心分配的端口/实例名 |
|
||||||
|
| CLI `--instance` 参数 | P5 RegistrationClient SDK 用此值作为注册服务名 |
|
||||||
|
| CLI `--port` 参数 | P0 ServiceEntry 的 port 字段来源 |
|
||||||
+1
-3
@@ -4,7 +4,5 @@
|
|||||||
# 启动时从 confs(CONFS_HOST:CONFS_PORT,默认 127.0.0.1:8010)拉取配置。
|
# 启动时从 confs(CONFS_HOST:CONFS_PORT,默认 127.0.0.1:8010)拉取配置。
|
||||||
cd "$(dirname "$0")" || exit
|
cd "$(dirname "$0")" || exit
|
||||||
|
|
||||||
# 等待依赖服务启动(confs/db)
|
# sleep 已移至 services.yaml 的 sleep_before 字段统一管理
|
||||||
sleep 2
|
|
||||||
|
|
||||||
exec ./build/gateway.out "$@"
|
exec ./build/gateway.out "$@"
|
||||||
+1
-1
@@ -13,4 +13,4 @@ if command -v setcap &>/dev/null; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec python3 redirect80.py
|
exec python3 redirect80.py "$@"
|
||||||
+1
-2
@@ -2,5 +2,4 @@
|
|||||||
cd "$(dirname "$0")" || exit
|
cd "$(dirname "$0")" || exit
|
||||||
source ./venv/bin/activate
|
source ./venv/bin/activate
|
||||||
#exec ./smtp.bin
|
#exec ./smtp.bin
|
||||||
sleep 2
|
exec python3 smtp_v2.py "$@"
|
||||||
exec python3 smtp_v2.py
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# 运行 WAF(需先 _set.sh 编译)
|
# 运行 WAF(需先 _set.sh 编译)
|
||||||
cd "$(dirname "$0")" || exit
|
cd "$(dirname "$0")" || exit
|
||||||
exec ./waf.bin -c config.yaml
|
exec ./waf.bin -c config.yaml "$@"
|
||||||
Reference in new issue
Block a user