This commit is contained in:
jonathang4 2025-08-27 17:30:04 +08:00
parent 7226255877
commit a73736cd26
5 changed files with 38 additions and 96 deletions

View File

@ -6,23 +6,6 @@ import logger from '@/lib/logger.ts';
export default {
// 获取当前服务器信息
get: {
'/servers/current': async () => {
try {
const heartbeatService = HeartbeatService.getInstance();
const serverInfo = heartbeatService.getServerInfo();
return new Response({
success: true,
data: serverInfo
});
} catch (error) {
logger.error('Failed to get current server info:', error);
return new Response({
success: false,
error: error.message
}, { statusCode: 500 });
}
},
// 获取所有活跃服务器
'/servers/active': async () => {

View File

@ -20,6 +20,8 @@ const startupTime = performance.now();
logger.info("Process id:", process.pid);
logger.info("Environment:", environment.env);
logger.info("Service name:", config.service.name);
logger.info("Service host:", config.service.host);
logger.info("Service port:", config.service.port);
// 初始化MongoDB连接
try {

View File

@ -70,7 +70,13 @@ export class ServiceConfig {
}
static load() {
const external = _.pickBy(environment, (v, k) => ["name", "host", "port"].includes(k) && !_.isUndefined(v));
// 从环境变量获取配置,支持 PM2 和其他方式设置的环境变量
const external = _.pickBy({
name: environment.name,
host: environment.host,
port: environment.port || (process.env.PORT ? Number(process.env.PORT) : undefined) // 支持 PM2 的 PORT 环境变量
}, (v, k) => !_.isUndefined(v));
if(!fs.pathExistsSync(CONFIG_PATH)) return new ServiceConfig(external);
const data = yaml.parse(fs.readFileSync(CONFIG_PATH).toString());
return new ServiceConfig({ ...data, ...external });

View File

@ -11,7 +11,6 @@ export class HeartbeatService {
private static instance: HeartbeatService;
private serverId: string;
private serverName: string;
private baseUrl: string;
private heartbeatTask: cron.ScheduledTask | null = null;
private isRunning: boolean = false;
@ -19,7 +18,6 @@ export class HeartbeatService {
// 优先从环境变量获取配置,否则使用默认值
this.serverId = process.env.SERVICE_ID || config.service?.name || 'jimeng-free-api';
this.serverName = process.env.SERVICE_NAME || this.serverId;
this.baseUrl = this.buildBaseUrl();
}
public static getInstance(): HeartbeatService {
@ -29,47 +27,6 @@ export class HeartbeatService {
return HeartbeatService.instance;
}
private buildBaseUrl(): string {
const host = process.env.HOST || config.service?.host || '0.0.0.0';
const port = process.env.PORT || config.service?.port || 3302;
// 如果明确指定了 BASE_URL直接使用
if (process.env.BASE_URL) {
return process.env.BASE_URL;
}
// 如果是 Docker 环境,使用容器名称
if (process.env.NODE_ENV === 'production' && process.env.CONTAINER_NAME) {
return `http://${process.env.CONTAINER_NAME}:${port}`;
}
// PM2 环境或Node.js直接启动环境
let targetHost = host;
if (host === '0.0.0.0') {
// 尝试获取本机的实际IP地址
targetHost = this.getLocalIP() || 'localhost';
}
return `http://${targetHost}:${port}`;
}
private getLocalIP(): string | null {
try {
const interfaces = os.networkInterfaces();
// 优先查找非回环的IPv4地址
for (const name of Object.keys(interfaces)) {
for (const iface of interfaces[name]) {
if (iface.family === 'IPv4' && !iface.internal) {
return iface.address;
}
}
}
} catch (error) {
logger.warn('Failed to get local IP:', error.message);
}
return null;
}
public async start(): Promise<void> {
if (this.isRunning) {
@ -140,26 +97,26 @@ export class HeartbeatService {
try {
const currentTime = Math.floor(Date.now() / 1000);
const serverData = {
server_id: this.serverId,
server_name: this.serverName,
base_url: this.baseUrl,
is_active: true,
last_heartbeat: currentTime,
heartbeat_interval: parseInt(process.env.HEARTBEAT_INTERVAL || '60'),
updated_at: currentTime
};
// 检查服务器是否已经存在
const existingServer = await JimengServer.findOne({ server_id: this.serverId });
await JimengServer.findOneAndUpdate(
{ server_id: this.serverId },
{
...serverData,
$setOnInsert: { created_at: currentTime }
},
{ upsert: true, new: true }
);
logger.info(`Server registered: ${this.serverId} at ${this.baseUrl}`);
if (!existingServer) {
logger.error(`服务器信息不存在 serverId: ${this.serverId}`);
// } else {
// // 服务器已存在:只更新心跳相关字段,不修改 base_url
// await JimengServer.findOneAndUpdate(
// { server_id: this.serverId },
// {
// server_name: this.serverName, // 允许更新服务器名称
// is_active: true,
// last_heartbeat: currentTime,
// heartbeat_interval: parseInt(process.env.HEARTBEAT_INTERVAL || '60'),
// updated_at: currentTime
// // 注意:不更新 base_url这由其他服务维护
// }
// );
// logger.info(`Server re-registered: ${this.serverId} (base_url preserved)`);
}
} catch (error) {
logger.error('Failed to register server:', error);
@ -171,16 +128,17 @@ export class HeartbeatService {
try {
const currentTime = Math.floor(Date.now() / 1000);
// 只更新心跳相关字段,不修改 base_url 等其他服务信息
await JimengServer.findOneAndUpdate(
{ server_id: this.serverId },
{
last_heartbeat: currentTime,
updated_at: currentTime,
is_active: true
last_heartbeat: currentTime, // 更新最后心跳时间
updated_at: currentTime, // 更新记录修改时间
// is_active: true // 标记为活跃状态
}
);
logger.debug(`Heartbeat sent for server ${this.serverId}`);
// logger.debug(`Heartbeat sent for server ${this.serverId}`);
} catch (error) {
logger.error('Failed to send heartbeat:', error);
@ -212,15 +170,6 @@ export class HeartbeatService {
process.exit(0);
}
public getServerInfo() {
return {
serverId: this.serverId,
serverName: this.serverName,
baseUrl: this.baseUrl,
isRunning: this.isRunning
};
}
// 获取所有活跃服务器
public static async getActiveServers(): Promise<IJimengServer[]> {
try {

View File

@ -14,6 +14,8 @@ services:
- SERVICE_ID=${SERVICE_ID:-jimeng-free-api}
- INSTANCE_ID=${INSTANCE_ID:-instance-1}
- SERVICE_NAME=${SERVICE_NAME:-jimeng-free-api}
- HOST=${HOST:-0.0.0.0}
- PORT=${API_PORT:-3302}
- MONGODB_URL=${MONGODB_URL:-mongodb://localhost:27017/jimeng-api}
- TOS_ACCESS_KEY_ID=${TOS_ACCESS_KEY_ID}
- TOS_ACCESS_KEY_SECRET=${TOS_ACCESS_KEY_SECRET}
@ -30,11 +32,11 @@ services:
- VIDEO_TASK_TIMEOUT=${VIDEO_TASK_TIMEOUT:-86400}
- RESULT_EXPIRE_TIME=${RESULT_EXPIRE_TIME:-86400}
ports:
- "${API_PORT:-3302}:3302"
- "${API_PORT:-3302}:${API_PORT:-3302}"
volumes:
- ./logs:/app/logs
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3302/ping"]
test: ["CMD", "curl", "-f", "http://localhost:${API_PORT:-3302}/ping"]
interval: 30s
timeout: 10s
retries: 3