feat(gateway): migrate configuration to confs service (v0.7.0)
Migrate gateway from local -i ini file to the unified confs configuration
service, following the same two-layer pattern as Python services (dnfs/db/static):
- Add confs/configs/gateway.ini with all existing settings plus new
[Downstream] section for db/captcha/smtp host:port (previously hardcoded).
- Conf.hpp: add fromString() to parse ini from text (confs response),
env()/env_int() static helpers for environment variables, public default
constructor, and empty-filename guard in file constructor.
- DbC.hpp: add init(host, port) static method and static _host/_port members,
replacing hardcoded "127.0.0.1":8005. Defaults preserved for backward compat.
- main.cpp:
* Rewrite config loading: bootstrap CONFS_HOST/CONFS_PORT from env
(default 127.0.0.1:8010), fetch gateway.ini via pymsg from confs
(retry_on_refused=true), parse with ConfIni::fromString().
* -i flag is now optional; when provided, reads local ini (dev/debug mode).
* Add downstream host/port globals (_DB_HOST/_DB_PORT, _CAPTCHA_HOST/_CAPTCHA_PORT,
_SMTP_HOST/_SMTP_PORT, _CONFS_HOST/_CONFS_PORT), populated from [Downstream].
* Environment variable overrides (highest priority): LISTEN_ADDR/LISTEN_PORT,
DB_HOST/DB_PORT, CAPTCHA_HOST/CAPTCHA_PORT, SMTP_HOST/SMTP_PORT.
* Config integrity validation: required fields (Server.address/port,
Proxy.default, Downstream.db_host/db_port) cause startup failure if missing.
* Initialize DbC::init() and logs().set_endpoint() after config load.
* Replace all hardcoded "127.0.0.1":8005/8008/8009 in captcha/smtp/db calls
with configurable globals.
* Add downstream service info to startup log output.
* Fix: -v/--version flag now actually prints version and exits.
* Bump version to 0.7.0.
- _run.sh: remove -i example.ini default; now starts without args (confs mode),
passes "$@" through for optional -i override.
- Update README with new config loading docs, Downstream config section,
updated directory structure, and v0.7.0 changelog.
This commit is contained in:
1 parent
de58c0487a
commit
9ccb9cbdca
6 files changed
+289
-108
No files matched your search
+37
-2
@@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <cstdlib>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
namespace property_tree = boost::property_tree;
|
||||
@@ -9,22 +12,54 @@ namespace qing {
|
||||
|
||||
class ConfIni {
|
||||
public:
|
||||
/// 默认构造(空配置,后续通过赋值覆盖,仅供 confs 加载流程内部使用)
|
||||
ConfIni() = default;
|
||||
|
||||
/// 从文件路径解析 ini(保留用于开发/调试模式)
|
||||
ConfIni(const std::string &filename) {
|
||||
if (filename.empty()) return; // 空文件名不报错,后续会通过赋值覆盖
|
||||
try {
|
||||
std::cout << "open and parse ini file: " << filename << std::endl;
|
||||
std::cout << "[conf] 从文件加载配置: " << filename << std::endl;
|
||||
property_tree::ini_parser::read_ini(filename, pt);
|
||||
}
|
||||
catch (const boost::property_tree::ini_parser_error& e) {
|
||||
std::cerr << "INI parsing error: " << e.what() << std::endl;
|
||||
std::cerr << "[conf] INI 解析错误: " << e.what() << std::endl;
|
||||
throw IniConfigureFileParseException("INI parsing error!");
|
||||
}
|
||||
}
|
||||
|
||||
/// 从 ini 文本字符串解析(用于从 confs 拉取后解析)
|
||||
static ConfIni fromString(const std::string &ini_text) {
|
||||
ConfIni c;
|
||||
try {
|
||||
std::istringstream iss(ini_text);
|
||||
property_tree::ini_parser::read_ini(iss, c.pt);
|
||||
}
|
||||
catch (const boost::property_tree::ini_parser_error& e) {
|
||||
std::cerr << "[conf] INI 文本解析错误: " << e.what() << std::endl;
|
||||
throw IniConfigureFileParseException("INI parsing error!");
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T get(const std::string &path, const T &_defaut) {
|
||||
return pt.get<T>(path, _defaut);
|
||||
}
|
||||
|
||||
/// 读取环境变量,不存在则返回默认值
|
||||
static std::string env(const char *name, const std::string &default_val = "") {
|
||||
const char *v = std::getenv(name);
|
||||
return v ? std::string(v) : default_val;
|
||||
}
|
||||
|
||||
static int env_int(const char *name, int default_val) {
|
||||
const char *v = std::getenv(name);
|
||||
if (!v || !*v) return default_val;
|
||||
try { return std::stoi(v); }
|
||||
catch (...) { return default_val; }
|
||||
}
|
||||
|
||||
class IniConfigureFileParseException: public std::exception {
|
||||
public:
|
||||
explicit IniConfigureFileParseException(const std::string &msg)
|
||||
|
||||
+27
-16
@@ -10,6 +10,12 @@ namespace qing {
|
||||
* smtp/captcha 等其他下游的超时常量见 main.cpp。 */
|
||||
static constexpr double DEFAULT_TIMEOUT = 5.0;
|
||||
|
||||
/// 初始化 db 服务地址(启动时从配置设置,默认 127.0.0.1:8005)
|
||||
static void init(const std::string& host, int port) {
|
||||
_host = host;
|
||||
_port = port;
|
||||
}
|
||||
|
||||
// 【保留】旧版 HTTP 接口:通过 HttpClient POST 到 dbv2 HTTP /execute 端点。
|
||||
// 保留用于兼容性参考,新代码优先使用 call_msg()(pymsg TCP 协议,更可靠)。
|
||||
static json::value call_http(json::value& params) {
|
||||
@@ -18,29 +24,34 @@ namespace qing {
|
||||
client.set_header("Content-Type: application/json");
|
||||
std::string payload = json::serialize(params);
|
||||
std::string res = "";
|
||||
client.post_stream_sync(_DBURL, payload, [&res](const auto& ret) {
|
||||
std::string url = "http://" + _host + ":" + std::to_string(_port) + "/execute";
|
||||
client.post_stream_sync(url, payload, [&res](const auto& ret) {
|
||||
res += ret;
|
||||
});
|
||||
return json::parse(res);
|
||||
}
|
||||
|
||||
// 新版 pymsg 接口:通过 MsgClient(TCP 长度前缀帧协议)调用 dbv2。
|
||||
// 自动添加 _route = "execute",返回 dbv2 pymsg 完整 JSON 响应
|
||||
// {"success":..., "data":[...]}。
|
||||
// 响应格式与 call_http 兼容,调用方可直接替换。
|
||||
// db 是强依赖,启用 retry_on_refused:db 未启动时阻塞等待,避免启动顺序问题。
|
||||
static json::value call_msg(const json::value& params,
|
||||
double timeout = DEFAULT_TIMEOUT) {
|
||||
json::value jv_route = params;
|
||||
jv_route.as_object()["_route"] = "execute";
|
||||
pmc::net::MsgClient client("127.0.0.1", 8005, "gateway");
|
||||
std::string resp = client.call(
|
||||
json::serialize(jv_route), timeout,
|
||||
/*retry_on_refused=*/true);
|
||||
return json::parse(resp);
|
||||
}
|
||||
// 自动添加 _route = "execute",返回 dbv2 pymsg 完整 JSON 响应
|
||||
// {"success":..., "data":[...]}。
|
||||
// 响应格式与 call_http 兼容,调用方可直接替换。
|
||||
// db 是强依赖,启用 retry_on_refused:db 未启动时阻塞等待,避免启动顺序问题。
|
||||
static json::value call_msg(const json::value& params,
|
||||
double timeout = DEFAULT_TIMEOUT) {
|
||||
json::value jv_route = params;
|
||||
jv_route.as_object()["_route"] = "execute";
|
||||
pmc::net::MsgClient client(_host, _port, "gateway");
|
||||
std::string resp = client.call(
|
||||
json::serialize(jv_route), timeout,
|
||||
/*retry_on_refused=*/true);
|
||||
return json::parse(resp);
|
||||
}
|
||||
|
||||
static const std::string& host() { return _host; }
|
||||
static int port() { return _port; }
|
||||
|
||||
private:
|
||||
static constexpr const char* _DBURL = "http://127.0.0.1:8005/execute";
|
||||
static inline std::string _host = "127.0.0.1";
|
||||
static inline int _port = 8005;
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user