mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
feat: sidecar 与 Info 响应加监听地址字段
This commit is contained in:
@@ -403,9 +403,14 @@ fn server_command(command: ServerCommands) -> ExitCode {
|
||||
_ => None,
|
||||
}),
|
||||
ServerCommands::Info => control_arm(&ServerRequest::Info, |response| match response {
|
||||
ServerResponse::Info { version, socket_path, pid } => {
|
||||
Some(format!("版本:{version}\nendpoint:{socket_path}\n进程号:{pid}"))
|
||||
}
|
||||
ServerResponse::Info {
|
||||
version,
|
||||
socket_path,
|
||||
pid,
|
||||
listen_addr,
|
||||
} => Some(format!(
|
||||
"版本:{version}\nendpoint:{socket_path}\n监听地址:{listen_addr}\n进程号:{pid}"
|
||||
)),
|
||||
_ => None,
|
||||
}),
|
||||
ServerCommands::Version => control_arm(&ServerRequest::Version, |response| match response {
|
||||
|
||||
@@ -306,6 +306,7 @@ mod tests {
|
||||
started_at: 0,
|
||||
starttime,
|
||||
port: 0,
|
||||
listen_addr: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -259,6 +259,7 @@ mod tests {
|
||||
started_at: 0,
|
||||
starttime,
|
||||
port: 0,
|
||||
listen_addr: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -172,8 +172,15 @@ pub enum ServerResponse {
|
||||
},
|
||||
/// 健康检查响应。
|
||||
Health { healthy: bool },
|
||||
/// 信息响应:版本、socket 路径、进程号。
|
||||
Info { version: String, socket_path: String, pid: u32 },
|
||||
/// 信息响应:版本、socket 路径、进程号、监听地址。
|
||||
Info {
|
||||
version: String,
|
||||
socket_path: String,
|
||||
pid: u32,
|
||||
/// 实际监听地址(bind 后的网络端点,控制客户端经协议层发现 server
|
||||
/// 可达接口;TCP 臂为 host:port,Unix 臂为 socket 路径)。
|
||||
listen_addr: String,
|
||||
},
|
||||
/// 关闭确认。
|
||||
Shutdown,
|
||||
/// 交接确认:旧 server 已受理,开始排空退出。
|
||||
@@ -434,6 +441,7 @@ mod tests {
|
||||
version: "0.8.23".into(),
|
||||
socket_path: "/tmp/oxide-server.sock".into(),
|
||||
pid: 1234,
|
||||
listen_addr: "127.0.0.1:4242".into(),
|
||||
},
|
||||
ServerResponse::Shutdown,
|
||||
ServerResponse::Yield,
|
||||
|
||||
@@ -153,6 +153,9 @@ struct ServerContext {
|
||||
pool_counters: Arc<PoolCounters>,
|
||||
// 监听端点文本形态(Unix 臂为路径、TCP 臂为 host:port),Info 响应用。
|
||||
socket_path: String,
|
||||
// 实际监听地址(bind 后取值:TCP 臂为 host:port、Unix 臂为 socket 路径),
|
||||
// Info 响应用,让控制客户端经协议层发现 server 网络端点。
|
||||
listen_addr: String,
|
||||
}
|
||||
|
||||
/// server 进程主体:初始化日志文件输出 → 启动时 liveness 扫描 → 认领 sidecar →
|
||||
@@ -240,6 +243,10 @@ pub fn run_server(config: &ServerConfig) -> Result<(), ServerError> {
|
||||
// 绑定监听器:stale socket 文件删一次重试,失败回滚 sidecar。
|
||||
let listener = bind_listener(config)?;
|
||||
|
||||
// 取实际监听地址(bind 后:TCP 臂为操作系统分配的实际端口,Unix 臂为
|
||||
// socket 路径),Info 响应用,让控制客户端经协议层发现 server 网络端点。
|
||||
let listen_addr = listener.local_addr().map_err(|e| ServerError::BindFailed(e.to_string()))?;
|
||||
|
||||
// 建内核(标准配置)与共享聚合计数器(全体 worker 池的增减累加到同一聚合)。
|
||||
let kernel = KernelCore::new(KernelConfig::standard());
|
||||
let counters = PoolCounters::shared();
|
||||
@@ -261,6 +268,7 @@ pub fn run_server(config: &ServerConfig) -> Result<(), ServerError> {
|
||||
in_flight: Arc::new(AtomicUsize::new(0)),
|
||||
pool_counters: counters,
|
||||
socket_path: config.endpoint.describe(),
|
||||
listen_addr,
|
||||
});
|
||||
|
||||
// accept 循环:非阻塞 accept 加 10 毫秒轮询加原子关闭标志。
|
||||
@@ -346,7 +354,10 @@ pub fn run_server_rm(config: &RmServerConfig) -> Result<(), ServerError> {
|
||||
shutdown: Arc::clone(&shutdown),
|
||||
in_flight: Arc::new(AtomicUsize::new(0)),
|
||||
pool_counters: counters,
|
||||
socket_path,
|
||||
// socket_path 与 listen_addr 同源:--rm 的 socket_path 已取 bind 后的
|
||||
// 实际地址(local_addr),Info 响应的监听地址与之一致。
|
||||
socket_path: socket_path.clone(),
|
||||
listen_addr: socket_path,
|
||||
});
|
||||
|
||||
// 空闲窗口一:等首个连接;空闲超时内无连接即干净退出。
|
||||
@@ -794,6 +805,7 @@ fn dispatch_control(request: &ServerRequest, ctx: &ServerContext) -> ServerRespo
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
socket_path: ctx.socket_path.clone(),
|
||||
pid: std::process::id(),
|
||||
listen_addr: ctx.listen_addr.clone(),
|
||||
},
|
||||
ServerRequest::Shutdown => {
|
||||
// 置关闭标志;主循环至多 10 毫秒内退出 accept 循环。
|
||||
@@ -1043,10 +1055,17 @@ mod tests {
|
||||
let mut stream = connect(&config);
|
||||
let response = send_and_recv(&mut stream, &ServerRequest::Info);
|
||||
match response {
|
||||
ServerResponse::Info { version, socket_path, pid } => {
|
||||
ServerResponse::Info {
|
||||
version,
|
||||
socket_path,
|
||||
pid,
|
||||
listen_addr,
|
||||
} => {
|
||||
assert_eq!(version, env!("CARGO_PKG_VERSION"), "版本应与构建期版本一致");
|
||||
assert_eq!(socket_path, config.endpoint.describe(), "socket 路径应与配置一致");
|
||||
assert_eq!(pid, std::process::id(), "进程号应为当前进程号");
|
||||
// Unix 臂:实际监听地址即 socket 路径,与配置端点一致。
|
||||
assert_eq!(listen_addr, config.endpoint.describe(), "监听地址应与配置一致(Unix 臂)");
|
||||
}
|
||||
other => panic!("应得 Info 帧,实得 {other:?}"),
|
||||
}
|
||||
|
||||
@@ -35,6 +35,9 @@ use serde::{Deserialize, Serialize};
|
||||
/// PID 复用判定用。
|
||||
/// - `port`:TCP 监听端口(机器可读形态),Unix 臂为 0;旧 sidecar 无该
|
||||
/// 字段时读回为 0(serde 缺省),探活裁决仍走 `socket_path` 文本。
|
||||
/// - `listen_addr`:监听地址(网络身份——server 可达的网络接口,安全边界
|
||||
/// 关注点:loopback-only 与 all-interfaces 的区分);旧 sidecar 无该字段
|
||||
/// 时读回为空串(serde 缺省)。
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct ServerIdentity {
|
||||
pub pid: u32,
|
||||
@@ -46,6 +49,11 @@ pub struct ServerIdentity {
|
||||
/// 读回为 0(serde 缺省),探活裁决走 socket_path 文本,行为不变。
|
||||
#[serde(default)]
|
||||
pub port: u16,
|
||||
/// 监听地址(网络身份:server 可达的网络接口,loopback-only 与
|
||||
/// all-interfaces 的区分);旧 sidecar 无该字段时读回为空串(serde
|
||||
/// 缺省),探活裁决仍走 socket_path 文本,行为不变。
|
||||
#[serde(default)]
|
||||
pub listen_addr: String,
|
||||
}
|
||||
|
||||
impl ServerIdentity {
|
||||
@@ -57,6 +65,8 @@ impl ServerIdentity {
|
||||
/// - `socket_path` 字段记监听端点的文本形态(`endpoint.describe()`),
|
||||
/// 字段名与 JSON 模式不变,旧 sidecar 可读。
|
||||
/// - `port` 取端点的 TCP 端口(Unix 臂无端口,记 0)。
|
||||
/// - `listen_addr` 取端点的文本形态(`endpoint.describe()`),与
|
||||
/// `socket_path` 同源同时机(认领时、bind 之前),记配置监听地址。
|
||||
/// - 非 Linux 宿主(`/proc` 缺位)时 `starttime` 填 0,交叉核对退化,
|
||||
/// liveness 由 endpoint 探活裁决。
|
||||
pub fn new(endpoint: &Endpoint, version: &str) -> Self {
|
||||
@@ -66,13 +76,15 @@ impl ServerIdentity {
|
||||
Endpoint::Tcp(addr) => addr.port(),
|
||||
Endpoint::Unix(_) => 0,
|
||||
};
|
||||
let socket_path = endpoint.describe();
|
||||
ServerIdentity {
|
||||
pid,
|
||||
socket_path: endpoint.describe(),
|
||||
socket_path: socket_path.clone(),
|
||||
version: version.to_string(),
|
||||
started_at,
|
||||
starttime: process_starttime(pid).unwrap_or(0),
|
||||
port,
|
||||
listen_addr: socket_path,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -424,6 +436,7 @@ mod tests {
|
||||
started_at: 0,
|
||||
starttime: 0,
|
||||
port: 0,
|
||||
listen_addr: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,7 +448,7 @@ mod tests {
|
||||
let id = ServerIdentity::new(&Endpoint::Unix(PathBuf::from("/tmp/oxide-test.sock")), "0.0.0");
|
||||
write_exclusive(&id, &path).expect("写 sidecar 应成功");
|
||||
let read = read_identity(&path).expect("读回 sidecar 应成功");
|
||||
assert_eq!(read, id, "五字段应逐字段一致");
|
||||
assert_eq!(read, id, "六字段应逐字段一致");
|
||||
}
|
||||
|
||||
/// 端口字段:TCP 端点记端点端口(机器可读形态),Unix 臂记 0。
|
||||
@@ -458,6 +471,7 @@ mod tests {
|
||||
let read = read_identity(&path).expect("读回 sidecar 应成功");
|
||||
assert_eq!(read, id, "字段应逐字段一致");
|
||||
assert_eq!(read.port, 4242, "port 字段应记端点端口");
|
||||
assert_eq!(read.listen_addr, "127.0.0.1:4242", "listen_addr 字段应记端点地址");
|
||||
}
|
||||
|
||||
/// 旧 sidecar(无 port 字段)读回:serde 缺省补 0,读回成功不判损坏。
|
||||
@@ -472,6 +486,7 @@ mod tests {
|
||||
.expect("写旧 sidecar 应成功");
|
||||
let id = read_identity(&path).expect("旧 sidecar 应可读回");
|
||||
assert_eq!(id.port, 0, "无 port 字段应读回 0");
|
||||
assert_eq!(id.listen_addr, "", "无 listen_addr 字段应读回空串");
|
||||
}
|
||||
|
||||
/// O_EXCL 排他:同路径二次 create_new 必得 AlreadyExists。
|
||||
|
||||
@@ -309,6 +309,7 @@ mod tests {
|
||||
started_at: 0,
|
||||
starttime: 0,
|
||||
port: 0,
|
||||
listen_addr: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user