Documentation
¶
Index ¶
- Constants
- func Dial(addr string) (net.Conn, error)
- func ExitInfo(ps *os.ProcessState) (exitCode int, signal string)
- func IgnoreBrokenPipe()
- func IsPIDAlive(pid int) bool
- func KillPIDTree(pid int) error
- func Listen(addr string) (net.Listener, error)
- func PIDFileName(pidDir, instanceUUID string) string
- func ParseAutoRestart(s string) bool
- func RemoveSocket(addr string)
- func Run(cfg WrapperConfig) error
- func RunWithReady(cfg WrapperConfig, ready chan<- struct{}) error
- func SocketAddr(pidDir, instanceUUID string) string
- func WaitForPriorExit(pidDir, uuid string)
- type Channel
- type ExitEvent
- type Flags
- type Frame
- type Header
- type InstanceState
- type PIDFile
- type PIDRecord
- type RingBuffer
- type Type
- type Wrapper
- type WrapperConfig
Constants ¶
const ( CtrlStop = "stop" CtrlKill = "kill" CtrlPing = "ping" )
controlCommand 是 Worker 通过 ChannelControl 下发的控制命令。 约定 payload 为 "stop" / "kill" / "ping" 文本。
const ( ControlStop = CtrlStop ControlKill = CtrlKill ControlPing = CtrlPing )
ControlStop / ControlKill / ControlPing 是导出的控制命令常量, 供 daemonStrategy 跨包引用。
const (
EnvWrapperConfig = "JM_DAEMON_WRAPPER_CONFIG" // JSON 编码的 WrapperConfig
)
环境变量键名约定。Worker spawn wrapper 时写入这些变量。
const EventJavaExit = "java_exit"
EventJavaExit 是 ExitEvent.Event 的取值:被托管进程非正常退出(FR-313)。 事件字段留作区分未来其他 wrapper 事件,Worker 侧按值过滤、未知事件忽略。
const HeaderSize = 8
const MaxPayloadSize = 4 * 1024 * 1024 // 4MB
Variables ¶
This section is empty.
Functions ¶
func ExitInfo ¶
func ExitInfo(ps *os.ProcessState) (exitCode int, signal string)
ExitInfo 从进程退出状态提取退出码与信号名(FR-313)。 ps 为 nil(Wait 出错且无退出状态)时退出码取 -1。信号仅 Unix 有意义:被信号终止时 返回 syscall.Signal 的字符串形式(如 killed/terminated);Windows 的 WaitStatus Signaled() 恒为 false,信号恒为空(与 spec「Windows 信号留空」一致)。
func IgnoreBrokenPipe ¶
func IgnoreBrokenPipe()
IgnoreBrokenPipe 让 wrapper 进程忽略 SIGPIPE(Unix)。
wrapper 的 stdout/stderr 由父 Worker 设为 OS 管道(见 process/daemon.go 的 newSlogWriter: 非 *os.File 的 io.Writer 会让 exec 建管道、读端留在 Worker 内)。Worker 重启/崩溃后管道读端 关闭,wrapper 下一次日志写 fd 1/2 会触发 SIGPIPE——Go 运行时对 fd 1/2 的 SIGPIPE 默认**终止 进程**,从而拖死本应存活的 daemon 游戏服(见 ADR-003 守护进程 Wrapper、FR-341)。
忽略后,写已断的 fd 返回 EPIPE(由 slog 静默丢弃该行)而不终止进程;wrapper 存活,等待 Worker 经 Unix Socket 重连接管。仅影响 wrapper 子进程自身的日志流,不影响游戏服 stdin/stdout(走独立 管道,随 socket 重连恢复)。
func IsPIDAlive ¶
IsPIDAlive 在 Linux/macOS 上用 signal 0 探测进程是否存在(不实际发送信号)。
func KillPIDTree ¶
KillPIDTree 按 PID 强杀整棵进程树(FR-325 接管兜底:只有 PID 记录、无 *exec.Cmd 句柄)。 与 killProcessTree 同源:杀 pid 所在进程组(负 pgid,SIGKILL),取不到 pgid 时回退杀单进程。
func RunWithReady ¶
func RunWithReady(cfg WrapperConfig, ready chan<- struct{}) error
RunWithReady 同 Run,并在 wrapper 监听就绪后向 ready 发送信号(非阻塞)。 ready 为 nil 时忽略。供测试/集成方等待 wrapper 可被拨号后再连接,消除竞态。
func SocketAddr ¶
SocketAddr 为实例生成跨平台的通信地址。 Linux/macOS:Unix Socket 文件路径(<pidDir>/<uuid>.sock)。 Windows:Named Pipe 名称(\\.\pipe\jianmanager-<uuid>)。 返回的地址可直接传给 Listen/Dial。
func WaitForPriorExit ¶
func WaitForPriorExit(pidDir, uuid string)
WaitForPriorExit 在(重新)启动 daemon 实例前,按 PID 文件等待上一代 wrapper/Java 进程完全退出。
背景:快速 stop→start 时,旧实例可能仍在优雅退出,其 Java 仍占着监听端口(如 25566)、 其 wrapper 仍占着通信 socket。此时直接 spawn 新 wrapper/Java 会因端口/地址冲突崩溃 (worker 日志可见 `wrapper 进程退出 err="exit status 1"`)。本函数把这一竞态收敛掉。
语义:PID 文件不存在(上一代已自清理)即视为已退出,立即返回;wrapper 与 Java PID 均不存活 时返回;超时后尽力而为返回(不无限期阻塞启动,避免旧进程卡死时永远起不来)。
Types ¶
type ExitEvent ¶
type ExitEvent struct {
// Event 事件类型,恒为 EventJavaExit。
Event string `json:"event"`
// ExitCode 进程退出码;无法获知时为 -1。
ExitCode int `json:"exit_code"`
// Signal 终止信号名(Unix,如 killed/terminated);Windows / 非信号退出为空。
Signal string `json:"signal,omitempty"`
// DurationMs 本次运行时长(毫秒)。
DurationMs int64 `json:"duration_ms"`
}
ExitEvent 是 wrapper 检测到被托管进程非正常退出时,经控制通道(ChannelControl + TypeEvent)上抛给 Worker 的事件负载(JSON,FR-313)。daemon 模式下进程由 wrapper 直接托管,退出码/信号只有 wrapper 能拿到,须经此事件转交 Worker 组装崩溃快照。
func DecodeExitEvent ¶
DecodeExitEvent 从事件帧负载解析退出事件;非 java_exit 事件返回 ok=false(忽略)。
type Header ¶
type Header struct {
Channel Channel // 2 bytes
Type Type // 1 byte
Flags Flags // 1 byte
Length uint32 // 4 bytes
}
Header 帧头 (8 字节)。
type InstanceState ¶
type InstanceState string
InstanceState 复用 process 包的状态语义(此处独立定义避免循环依赖)。
const ( StateStopped InstanceState = "STOPPED" StateStarting InstanceState = "STARTING" StateRunning InstanceState = "RUNNING" StateStopping InstanceState = "STOPPING" StateCrashed InstanceState = "CRASHED" )
type PIDFile ¶
type PIDFile struct {
// contains filtered or unexported fields
}
PIDFile PID 文件管理。 旧版只存裸 PID 数字,新版存 JSON(PIDRecord)。Read 同时兼容两种格式。
func (*PIDFile) ReadRecord ¶
ReadRecord 读取完整恢复记录。
func (*PIDFile) WriteRecord ¶
WriteRecord 写入完整恢复记录(JSON)。
type PIDRecord ¶
type PIDRecord struct {
WrapperPID int `json:"wrapper_pid"`
JavaPID int `json:"java_pid"`
SocketAddr string `json:"socket_addr"` // Unix Socket 路径或 Named Pipe 名称
InstanceUUID string `json:"instance_uuid"`
WorkDir string `json:"work_dir"` // 实例工作目录,供 Worker 重启恢复后做文件/配置操作
ProbePort int `json:"probe_port,omitempty"` // ServerProbe /metrics 端口,供 Worker 重启恢复后心跳继续自采(FR-060)
}
PIDRecord 记录 daemon wrapper 的恢复信息。 Worker 重启后读取此文件:wrapper pid 存活则 reconnect socket 恢复管理, 否则清理文件。java pid 用于诊断/展示。
type RingBuffer ¶
type RingBuffer struct {
// contains filtered or unexported fields
}
RingBuffer 环形缓冲区,用于存储最近的输出。 支持多个观察者同时读取。
type Type ¶
type Type uint8
Type 帧类型。
const ( TypeData Type = 0x01 TypeCommand Type = 0x02 TypeResponse Type = 0x03 TypeHeartbeat Type = 0x04 // TypeEvent 事件帧(wrapper→Worker 单向,ChannelControl,payload=JSON,FR-313)。 // 版本互不炸:老 Worker 的 readLoop 只消费 stdout/stderr 通道、忽略未知帧; // 老 wrapper 从不发事件帧,新 Worker 收不到即无快照,均不影响既有链路。 TypeEvent Type = 0x05 )
type Wrapper ¶
type Wrapper struct {
// contains filtered or unexported fields
}
Wrapper 是 daemon wrapper 子进程的运行体。 它作为 Java 进程的父进程,负责:启动/重启 Java、监听 socket、 与 Worker 双向帧通信(转发 stdio + 接收控制命令)、维护 PID 文件。 参见 ADR-003: 守护进程 Wrapper 模式。
type WrapperConfig ¶
type WrapperConfig struct {
InstanceUUID string `json:"instance_uuid"`
StartCommand string `json:"start_command"`
// StopCommand 优雅停止时写入进程 stdin 的命令(不含换行)。
// 由 Control Plane 按实例角色派生(MC 后端用 stop,代理用 end)。
// 为空时 wrapper 回退到 MC 的 "stop",保证旧实例/恢复路径行为不变。
StopCommand string `json:"stop_command,omitempty"`
WorkDir string `json:"work_dir"`
EnvVars map[string]string `json:"env_vars"`
JavaHome string `json:"java_home,omitempty"`
JDKBinPath string `json:"jdk_bin_path,omitempty"`
AutoRestart bool `json:"auto_restart"`
PIDDir string `json:"pid_dir"`
StartTimeout time.Duration `json:"start_timeout"` // Java 启动到首字节输出的等待(0=不限)
// ProbePort 透传到 PID 记录,使 Worker 重启恢复后心跳继续自采该实例 ServerProbe 指标(FR-060)。
ProbePort int `json:"probe_port,omitempty"`
// GracefulStopTimeoutSeconds 优雅停止后等待进程自行退出的上限(秒,CP 从平台设置
// graceful_stop.timeout 取生效值后于启动时下发,FR-063)。>0 时 wrapper 用它做超时强杀兜底;
// 0=未指定,回退环境变量/默认。值在启动时定型,故对设置变更后「新启动」的实例生效。
GracefulStopTimeoutSeconds int `json:"graceful_stop_timeout_seconds,omitempty"`
}
WrapperConfig 是 daemon wrapper 子进程的启动配置。 通过环境变量从 Worker 传递给 wrapper 子进程(避免命令行长度/转义问题)。 WrapperConfig 是 daemon wrapper 子进程的启动配置。 通过环境变量从 Worker 传递给 wrapper 子进程(避免命令行长度/转义问题)。
func ParseWrapperConfigFromEnv ¶
func ParseWrapperConfigFromEnv() (WrapperConfig, error)
ParseWrapperConfigFromEnv 从环境变量解析 wrapper 配置。 供 cmd/worker 的 daemon 子命令调用。