feat: 增强Kafka消费者配置并完善action_type分类逻辑
- 支持多实例Kafka消费者,增加并发处理能力 - 新增Kafka配置参数:最大飞行中消息数、获取字节数、等待时间等 - 完善action_type分类逻辑,根据dev_type映射为"用户操作"或"设备回路状态" - 临时支持hex格式udp_raw自动转换为base64存储 - 增加extra字段支持上游扩展数据传递 - 优化数据库初始化脚本查找路径 - 更新PM2配置,修改应用名称和端口 - 清理开发环境日志文件,将dist目录加入.gitignore - 更新相关文档说明
This commit is contained in:
@@ -3,29 +3,54 @@ import { logger } from '../utils/logger.js';
|
||||
|
||||
const { ConsumerGroup } = kafka;
|
||||
|
||||
export const createKafkaConsumer = ({ kafkaConfig, onMessage, onError }) => {
|
||||
const createOneConsumer = ({ kafkaConfig, onMessage, onError, instanceIndex }) => {
|
||||
const kafkaHost = kafkaConfig.brokers.join(',');
|
||||
const clientId = instanceIndex === 0 ? kafkaConfig.clientId : `${kafkaConfig.clientId}-${instanceIndex}`;
|
||||
const id = `${clientId}-${process.pid}-${Date.now()}`;
|
||||
const maxInFlight = Number.isFinite(kafkaConfig.maxInFlight) ? kafkaConfig.maxInFlight : 50;
|
||||
let inFlight = 0;
|
||||
|
||||
const consumer = new ConsumerGroup(
|
||||
{
|
||||
kafkaHost,
|
||||
groupId: kafkaConfig.groupId,
|
||||
clientId: kafkaConfig.clientId,
|
||||
clientId,
|
||||
id,
|
||||
fromOffset: 'earliest',
|
||||
protocol: ['roundrobin'],
|
||||
outOfRangeOffset: 'latest',
|
||||
autoCommit: true,
|
||||
autoCommitIntervalMs: kafkaConfig.autoCommitIntervalMs,
|
||||
fetchMaxBytes: kafkaConfig.fetchMaxBytes,
|
||||
fetchMinBytes: kafkaConfig.fetchMinBytes,
|
||||
fetchMaxWaitMs: kafkaConfig.fetchMaxWaitMs,
|
||||
sasl: kafkaConfig.sasl
|
||||
},
|
||||
kafkaConfig.topic
|
||||
);
|
||||
|
||||
const tryResume = () => {
|
||||
if (inFlight < maxInFlight) {
|
||||
consumer.resume();
|
||||
}
|
||||
};
|
||||
|
||||
consumer.on('message', (message) => {
|
||||
onMessage(message).catch((error) => {
|
||||
logger.error('Kafka message handling failed', { error: error?.message });
|
||||
if (onError) {
|
||||
onError(error, message);
|
||||
}
|
||||
});
|
||||
inFlight += 1;
|
||||
if (inFlight >= maxInFlight) {
|
||||
consumer.pause();
|
||||
}
|
||||
Promise.resolve(onMessage(message))
|
||||
.catch((error) => {
|
||||
logger.error('Kafka message handling failed', { error: error?.message });
|
||||
if (onError) {
|
||||
onError(error, message);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
inFlight -= 1;
|
||||
tryResume();
|
||||
});
|
||||
});
|
||||
|
||||
consumer.on('error', (error) => {
|
||||
@@ -37,3 +62,14 @@ export const createKafkaConsumer = ({ kafkaConfig, onMessage, onError }) => {
|
||||
|
||||
return consumer;
|
||||
};
|
||||
|
||||
export const createKafkaConsumers = ({ kafkaConfig, onMessage, onError }) => {
|
||||
const instances = Number.isFinite(kafkaConfig.consumerInstances) ? kafkaConfig.consumerInstances : 1;
|
||||
const count = Math.max(1, instances);
|
||||
return Array.from({ length: count }, (_, idx) =>
|
||||
createOneConsumer({ kafkaConfig, onMessage, onError, instanceIndex: idx })
|
||||
);
|
||||
};
|
||||
|
||||
export const createKafkaConsumer = ({ kafkaConfig, onMessage, onError }) =>
|
||||
createKafkaConsumers({ kafkaConfig, onMessage, onError })[0];
|
||||
|
||||
Reference in New Issue
Block a user