diff --git a/app/common/service/HostService.php b/app/common/service/HostService.php new file mode 100644 index 0000000..50feea7 --- /dev/null +++ b/app/common/service/HostService.php @@ -0,0 +1,14 @@ +getMessage()); + } + + return $newHostId; + } + + /** + * 主机注册与心跳更新 + * 这是一个原子操作,如果主机不存在则创建,如果存在则更新。 + */ + public static function heartbeat() + { + $hostId = self::getHostId(); + if (empty($hostId)) { + Log::error('无法获取当前主机ID,心跳更新失败'); + return; + } + + try { + // findOrEmpty可以避免查询不到时抛出异常 + $host = SystemHost::where('host_id', $hostId)->findOrEmpty(); + + // 收集动态性能指标 + $data = self::collectHostMetrics(); + + if ($host->isEmpty()) { + // 首次注册:补充一次性的静态信息 + $data['host_id'] = $hostId; + $data = array_merge($data, self::collectStaticInfo()); + SystemHost::create($data); + Log::info("主机 [{$hostId}] 已成功注册并上线。"); + } else { + // 后续心跳:仅更新动态信息 + $host->save($data); + } + } catch (\Exception $e) { + Log::error("主机 [{$hostId}] 心跳更新失败: " . $e->getMessage()); + } + } + + /** + * 收集主机的动态性能指标 (不依赖任何外部系统命令) + * @return array + */ + public static function collectHostMetrics(): array + { + // 获取CPU平均负载 (如果函数存在且未被禁用) + $cpuLoad = null; + if (function_exists('sys_getloadavg')) { + $load = sys_getloadavg(); + $cpuLoad = is_array($load) ? implode(',', array_map(fn($l) => round($l, 2), $load)) : null; + } + + return [ + 'status' => 1, + 'last_heartbeat_at' => date('Y-m-d H:i:s'), + 'ip_address' => gethostbyname(gethostname()), + 'cpu_load' => $cpuLoad, + 'memory_usage' => memory_get_usage(), // false: 获取脚本自身内存占用 + 'disk_free' => disk_free_space(App::getRootPath()), + 'disk_total' => disk_total_space(App::getRootPath()), + ]; + } + + /** + * 收集主机的静态信息 (仅在首次注册时调用) + * @return array + */ + public static function collectStaticInfo(): array + { + return [ + 'os_info' => php_uname(), + 'php_version' => PHP_VERSION, + ]; + } +}