钉钉 AI 客服:消息队列设计

2 阅读1分钟

钉钉 AI 客服:消息队列设计

消息队列是解耦和高可用的关键。


一、为什么需要消息队列?

场景问题解决
高并发请求堆积异步处理
服务解耦依赖故障缓冲
削峰填谷流量突增平滑处理

二、Redis 消息队列

2.1 简单队列

// 生产者
await redis.lpush('chat:queue', JSON.stringify({ userId, message }));

// 消费者
while (true) {
  const data = await redis.brpop('chat:queue', 0);
  const { userId, message } = JSON.parse(data[1]);
  await processChat(userId, message);
}

2.2 延迟队列

// 5 秒后处理
await redis.zadd('delay:queue', Date.now() + 5000, JSON.stringify(task));

// 消费延迟任务
const tasks = await redis.zrangebyscore('delay:queue', 0, Date.now());

三、RabbitMQ 配置

3.1 队列声明

const amqp = require('amqplib');

async function setup() {
  const conn = await amqp.connect('amqp://localhost');
  const ch = await conn.createChannel();
  
  await ch.assertQueue('chat:process', { durable: true });
  await ch.assertQueue('chat:result', { durable: true });
  
  return { conn, ch };
}

3.2 消息发送

async function sendChat(ch, message) {
  ch.sendToQueue('chat:process', Buffer.from(JSON.stringify(message)), {
    persistent: true,
    expiration: 60000  // 60 秒过期
  });
}

3.3 消息消费

ch.consume('chat:process', async (msg) => {
  try {
    const data = JSON.parse(msg.content.toString());
    await processChat(data);
    ch.ack(msg);  // 确认消息
  } catch (e) {
    ch.nack(msg, false, true);  // 重新入队
  }
});

四、消息可靠性

4.1 消息确认

// 生产者确认
ch.publish('exchange', 'routing', content, { mandatory: true });
ch.on('return', (msg) => console.log('消息被退回'));

// 消费者确认
ch.consume('queue', (msg) => {
  process(msg);
  ch.ack(msg);
});

4.2 持久化

// 队列持久化
await ch.assertQueue('queue', { durable: true });

// 消息持久化
ch.sendToQueue('queue', content, { persistent: true });

五、消息重试

5.1 重试机制

const MAX_RETRIES = 3;

async function processWithRetry(msg) {
  const data = JSON.parse(msg.content.toString());
  const retries = data.retries || 0;
  
  try {
    await process(data);
    return true;
  } catch (e) {
    if (retries < MAX_RETRIES) {
      data.retries = retries + 1;
      await sendToRetryQueue(data);
      return false;
    }
    await sendToDeadLetter(data);
    return false;
  }
}

5.2 死信队列

await ch.assertQueue('dead:letter', { durable: true });

await ch.assertQueue('main:queue', {
  durable: true,
  deadLetterExchange: '',
  deadLetterRoutingKey: 'dead:letter'
});

六、监控告警

6.1 队列监控

setInterval(async () => {
  const count = await redis.llen('chat:queue');
  if (count > 100) {
    await sendAlert(`队列堆积:${count} 条`);
  }
}, 60000);

项目地址:GitHub - dingtalk-connector-pro 有问题欢迎 Issue 或评论区交流