feat: 实现Redis集成与Kafka消息处理优化
- 新增Redis集成模块,支持心跳写入与控制台日志队列 - 优化Kafka消费者实现,支持多实例与自动重连 - 改进消息处理器,支持批量处理与多层解码 - 更新数据库表结构,调整字段类型与约束 - 添加Redis与Kafka的配置项和环境变量支持 - 补充测试用例和文档说明
This commit is contained in:
60
src/index.js
60
src/index.js
@@ -3,6 +3,7 @@ import config from './config/config.js';
|
||||
import { KafkaConsumer } from './kafka/consumer.js';
|
||||
import { HeartbeatProcessor } from './processor/heartbeatProcessor.js';
|
||||
import { DatabaseManager } from './db/databaseManager.js';
|
||||
import { RedisIntegration } from './redis/redisIntegration.js';
|
||||
|
||||
class WebBLSHeartbeatServer {
|
||||
constructor() {
|
||||
@@ -10,48 +11,69 @@ class WebBLSHeartbeatServer {
|
||||
this.kafkaConsumer = null;
|
||||
this.heartbeatProcessor = null;
|
||||
this.databaseManager = null;
|
||||
this.redis = null;
|
||||
this.consumers = null;
|
||||
}
|
||||
|
||||
async start() {
|
||||
try {
|
||||
// 初始化 Redis(按协议写入心跳与控制台日志)
|
||||
this.redis = new RedisIntegration(this.config.redis);
|
||||
await this.redis.connect();
|
||||
this.redis.startHeartbeat();
|
||||
|
||||
// 初始化数据库连接
|
||||
this.databaseManager = new DatabaseManager(this.config.db);
|
||||
this.databaseManager = new DatabaseManager({ ...this.config.db, maxConnections: 1 });
|
||||
await this.databaseManager.connect();
|
||||
console.log('数据库连接成功');
|
||||
await this.redis?.info('数据库连接成功', { module: 'db' });
|
||||
|
||||
// 初始化处理器
|
||||
this.heartbeatProcessor = new HeartbeatProcessor(
|
||||
this.config.processor,
|
||||
this.databaseManager
|
||||
);
|
||||
// 初始化处理器(共享批处理队列)
|
||||
this.heartbeatProcessor = new HeartbeatProcessor(this.config.processor, this.databaseManager);
|
||||
|
||||
// 初始化Kafka消费者
|
||||
this.kafkaConsumer = new KafkaConsumer(
|
||||
this.config.kafka,
|
||||
this.heartbeatProcessor.processMessage.bind(this.heartbeatProcessor)
|
||||
);
|
||||
await this.kafkaConsumer.connect();
|
||||
await this.kafkaConsumer.subscribe();
|
||||
await this.kafkaConsumer.startConsuming();
|
||||
console.log('Kafka消费者启动成功');
|
||||
// 在单进程内启动 N 个消费者实例(与分区数匹配)
|
||||
const instances = Math.max(1, Number(this.config.kafka?.consumerInstances ?? 1));
|
||||
this.consumers = [];
|
||||
for (let i = 0; i < instances; i++) {
|
||||
const consumer = new KafkaConsumer(
|
||||
{ ...this.config.kafka, consumerInstanceIndex: i },
|
||||
this.heartbeatProcessor.processMessage.bind(this.heartbeatProcessor)
|
||||
);
|
||||
await consumer.connect();
|
||||
await consumer.subscribe();
|
||||
await consumer.startConsuming();
|
||||
this.consumers.push({ consumer });
|
||||
}
|
||||
console.log(`Kafka消费者启动成功,共 ${instances} 个实例`);
|
||||
await this.redis?.info('Kafka消费者启动成功', { module: 'kafka', topic: this.config.kafka?.topic, instances });
|
||||
|
||||
console.log('BLS心跳接收端启动成功');
|
||||
await this.redis?.info('BLS心跳接收端启动成功', { module: 'app' });
|
||||
} catch (error) {
|
||||
console.error('启动失败:', error);
|
||||
await this.redis?.error('启动失败', { module: 'app', error: String(error?.message ?? error) });
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async stop() {
|
||||
try {
|
||||
if (this.kafkaConsumer) {
|
||||
await this.kafkaConsumer.stopConsuming();
|
||||
await this.kafkaConsumer.disconnect();
|
||||
if (this.consumers && Array.isArray(this.consumers)) {
|
||||
for (const { consumer } of this.consumers) {
|
||||
await consumer.stopConsuming();
|
||||
await consumer.disconnect();
|
||||
}
|
||||
this.consumers = null;
|
||||
}
|
||||
|
||||
if (this.databaseManager) {
|
||||
await this.databaseManager.disconnect();
|
||||
}
|
||||
|
||||
if (this.redis) {
|
||||
await this.redis.info('BLS心跳接收端已停止', { module: 'app' });
|
||||
await this.redis.disconnect();
|
||||
}
|
||||
|
||||
console.log('BLS心跳接收端已停止');
|
||||
} catch (error) {
|
||||
@@ -75,4 +97,4 @@ process.on('SIGTERM', () => {
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
export { WebBLSHeartbeatServer };
|
||||
export { WebBLSHeartbeatServer };
|
||||
|
||||
Reference in New Issue
Block a user