mcpField
U
using-message-queues

using-message-queues

github.com/ancoleman开发52587 次安装46 周前更新
代码仓库

关于 using-message-queues

using-message-queues 是面向开发者的消息队列与事件驱动架构指南,帮助按场景选择代理,并实现后台任务、事件流和复杂工作流。

主要功能

  1. 01按场景选择消息代理
  2. 02后台任务处理模式
  3. 03事件流与日志聚合
  4. 04死信队列和幂等处理
  5. 05队列状态的 SSE 更新

适用场景

  1. 01将耗时操作移出 HTTP 请求
  2. 02处理邮件发送或图像调整等后台任务
  3. 03构建订单处理等多步骤工作流
  4. 04将事件流用于分析管道

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ancoleman/ai-design-components --skill using-message-queues

安装后在 Claude Code 中输入/using-message-queues确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

outputs.yaml
examples/bullmq-webhook-processor/
README.md
examples/celery-image-processing/
README.md
examples/kafka-python/
consumer.py
producer.py
README.md
examples/temporal-order-processing/
activities.py
workflow.py
examples/temporal-order-saga/
README.md
references/
bullmq.md
celery.md
event-patterns.md
kafka.md
nats.md
rabbitmq.md
redis-streams.md
temporal-workflows.md
scripts/
kafka_producer_consumer.py
validate_message_schema.py

详细介绍

消息队列

为事件驱动架构、后台任务处理和服务解耦实现异步通信模式。

何时使用此技能

在以下情况下使用消息队列:

  • 长时间运行的操作会阻塞 HTTP 请求(报告生成、视频处理)
  • 需要服务解耦(微服务、事件驱动架构)
  • 需要可靠投递(支付处理、订单履约)
  • 用于分析的事件流(日志聚合、指标管道)
  • 复杂流程的工作流编排(多步骤 Saga、人工介入)
  • 后台任务处理(发送邮件、调整图像大小)

消息代理选择决策树

根据主要需求选择消息代理:

事件流 / 日志聚合

→ Apache Kafka

  • 吞吐量:500K-1M msg/s
  • 重放事件(事件溯源)
  • 精确一次语义
  • 长期保留
  • 用途:分析管道、CQRS、事件溯源
简单的后台任务

→ 任务队列

  • Python → Celery + Redis
  • TypeScript → BullMQ + Redis
  • Go → Asynq + Redis
  • 用途:发送邮件、生成报告、Webhooks
复杂工作流 / Saga

→ Temporal

  • 持久化执行(重启后仍可继续)
  • 支持 Saga 模式
  • 人工介入工作流
  • 用途:订单处理、AI Agent 编排
请求-响应 / RPC 模式

→ NATS

  • 内置请求-响应
  • 亚毫秒延迟
  • 云原生、运维简单
  • 用途:微服务 RPC、IoT 命令与控制
复杂消息路由

→ RabbitMQ

  • 交换机(direct、topic、fanout、headers)
  • 死信交换机
  • 消息 TTL、优先级
  • 用途:多消费者模式、发布/订阅
已在使用 Redis

→ Redis Streams

  • 无需新增基础设施
  • 简单的消费者组
  • 中等吞吐量(100K+ msg/s)
  • 用途:通知队列、简单任务队列

性能对比

消息代理吞吐量延迟(p99)最适合
Kafka500K-1M msg/s10-50ms事件流
NATS JetStream200K-400K msg/s亚毫秒至 5ms云原生微服务
RabbitMQ50K-100K msg/s5-20ms任务队列、复杂路由
Redis Streams100K+ msg/s亚毫秒简单队列、缓存

快速入门示例

Kafka 生产者/消费者(Python)

查看 examples/kafka-python/ 获取可运行代码。

from confluent_kafka import Producer, Consumer

# Producer
producer = Producer({'bootstrap.servers': 'localhost:9092'})
producer.produce('orders', key='order_123', value='{"status": "created"}')
producer.flush()

# Consumer
consumer = Consumer({
    'bootstrap.servers': 'localhost:9092',
    'group.id': 'order-processors',
    'auto.offset.reset': 'earliest'
})
consumer.subscribe(['orders'])

while True:
    msg = consumer.poll(1.0)
    if msg is not None:
        process_order(msg.value())
Celery 后台任务(Python)

查看 examples/celery-image-processing/ 获取完整实现。

from celery import Celery

app = Celery('tasks', broker='redis://localhost:6379')

@app.task(bind=True, max_retries=3)
def process_image(self, image_url: str):
    try:
        result = expensive_image_processing(image_url)
        return result
    except RecoverableError as e:
        raise self.retry(exc=e, countdown=60)
BullMQ 任务处理(TypeScript)

查看 examples/bullmq-webhook-processor/ 获取完整实现。

import { Queue, Worker } from 'bullmq'

const queue = new Queue('webhooks', {
  connection: { host: 'localhost', port: 6379 }
})

// Enqueue job
await queue.add('send-webhook', {
  url: 'https://example.com/webhook',
  payload: { event: 'order.created' }
})

// Process jobs
const worker = new Worker('webhooks', async job => {
  await fetch(job.data.url, {
    method: 'POST',
    body: JSON.stringify(job.data.payload)
  })
}, { connection: { host: 'localhost', port: 6379 } })
Temporal 工作流编排

查看 examples/temporal-order-saga/ 获取 Saga 模式实现。

from temporalio import workflow, activity
from datetime import timedelta

@workflow.defn
class OrderSagaWorkflow:
    @workflow.run
    async def run(self, order_id: str) -> str:
        # Step 1: Reserve inventory
        inventory_id = await workflow.execute_activity(
            reserve_inventory,
            order_id,
            start_to_close_timeout=timedelta(seconds=10),
        )

        # Step 2: Charge payment
        payment_id = await workflow.execute_activity(
            charge_payment,
            order_id,
            start_to_close_timeout=timedelta(seconds=30),
        )

        return f"Order {order_id} completed"

核心模式

事件命名约定

使用:Domain.Entity.Action.Version

示例:

  • order.created.v1
  • user.profile.updated.v2
  • payment.failed.v1
事件架构结构
{
  "event_type": "order.created.v2",
  "event_id": "uuid-here",
  "timestamp": "2025-12-02T10:00:00Z",
  "version": "2.0",
  "data": {
    "order_id": "ord_123",
    "customer_id": "cus_456"
  },
  "metadata": {
    "producer": "order-service",
    "trace_id": "abc123",
    "correlation_id": "xyz789"
  }
}
死信队列模式

达到最大重试次数后,将失败消息路由到死信队列(DLQ):

@app.task(bind=True, max_retries=3)
def process_order(self, order_id: str):
    try:
        result = perform_processing(order_id)
        return result
    except UnrecoverableError as e:
        send_to_dlq(order_id, str(e))
        raise Reject(e, requeue=False)
精确一次处理的幂等性
@app.post("/process")
async def process_payment(
    payment_data: dict,
    idempotency_key: str = Header(None)
):
    # Check if already processed
    cached_result = redis_client.get(f"idempotency:{idempotency_key}")
    if cached_result:
        return {"status": "already_processed"}

    result = process_payment_logic(payment_data)
    redis_client.setex(f"idempotency:{idempotency_key}", 86400, result)
    return {"status": "processed", "result": result}

前端集成

通过 SSE 更新任务状态
# FastAPI endpoint for real-time job status
@app.get("/status/{task_id}")
async def task_status_stream(task_id: str):
    async def event_generator():
        while True:
            task = celery_app.AsyncResult(task_id)

            if task.state == 'PROGRESS':
                yield {"event": "progress", "data": task.info.get('progress', 0)}
            elif task.state == 'SUCCESS':
                yield {"event": "complete", "data": task.result}
                break

            await asyncio.sleep(0.5)

    return EventSourceResponse(event_generator())
React 组件
export function JobStatus({ jobId }: { jobId: string }) {
  const [progress, setProgress] = useState(0)

  useEffect(() => {
    const eventSource = new EventSource(`/api/status/${jobId}`)

    eventSource.addEventListener('progress', (e) => {
      setProgress(JSON.parse(e.data))
    })

    eventSource.addEventListener('complete', (e) => {
      toast({ title: 'Job complete', description: JSON.parse(e.data) })
      eventSource.close()
    })

    return () => eventSource.close()
  }, [jobId])

  return <ProgressBar value={progress} />
}

详细指南

如需完整文档,请参阅参考文件:

消息代理专属指南
  • Kafka:参阅 references/kafka.md,了解分区、消费者组和精确一次语义
  • RabbitMQ:参阅 references/rabbitmq.md,了解交换机、绑定和路由模式
  • NATS:参阅 references/nats.md,了解 JetStream 和请求-响应模式
  • Redis Streams:参阅 references/redis-streams.md,了解消费者组和确认机制
任务队列指南
  • Celery:参阅 references/celery.md,了解周期性任务、canvas(工作流)和监控
  • BullMQ:参阅 references/bullmq.md,了解任务优先级、流程和 Bull Board 监控
  • Temporal:参阅 references/temporal-workflows.md,了解 Saga 模式、信号和查询
模式指南
  • 事件模式:请参阅 references/event-patterns.md,了解事件溯源、CQRS 和 outbox 模式

应避免的常见反模式

1. 为长时间运行的操作使用同步 API
# ❌ BAD: Blocks request thread
@app.post("/generate-report")
def generate_report(user_id: str):
    report = expensive_computation(user_id)  # 5 minutes!
    return report

# ✅ GOOD: Enqueue background job
@app.post("/generate-report")
async def generate_report(user_id: str):
    task = generate_report_task.delay(user_id)
    return {"task_id": task.id}
2. 非幂等消费者
# ❌ BAD: Processes duplicates
@app.task
def send_email(email: str):
    send_email_service(email)  # Sends twice if retried!

# ✅ GOOD: Idempotent with deduplication
@app.task
def send_email(email: str, idempotency_key: str):
    if redis.exists(f"sent:{idempotency_key}"):
        return "already_sent"
    send_email_service(email)
    redis.setex(f"sent:{idempotency_key}", 86400, "1")
3. 忽略死信队列
# ❌ BAD: Failed messages lost forever
@app.task(max_retries=3)
def risky_task(data):
    process(data)  # If all retries fail, data disappears

# ✅ GOOD: DLQ for manual inspection
@app.task(max_retries=3)
def risky_task(data):
    try:
        process(data)
    except Exception as e:
        if self.request.retries >= 3:
            send_to_dlq(data, str(e))
        raise
4. 使用 Kafka 实现请求-响应
# ❌ BAD: Kafka is not designed for RPC
def get_user_profile(user_id: str):
    kafka_producer.send("user_requests", {"user_id": user_id})
    # How to correlate response? Kafka is asynchronous!

# ✅ GOOD: Use NATS request-reply or HTTP/gRPC
response = await nats.request("user.profile", user_id.encode())

库推荐

Context7 调研

Confluent Kafka(Python)

  • Context7 ID:/confluentinc/confluent-kafka-python
  • 信任评分:68.8/100
  • 代码片段:192+
  • 可用于生产环境的 Python Kafka 客户端

Temporal

  • Context7 ID:/websites/temporal_io
  • 信任评分:80.9/100
  • 代码片段:3,769+
  • 用于持久执行的工作流编排
安装

Python:

pip install confluent-kafka celery[redis] temporalio aio-pika redis

TypeScript/Node.js:

npm install kafkajs bullmq @temporalio/client amqplib ioredis

Rust:

cargo add rdkafka lapin async-nats redis

Go:

go get github.com/confluentinc/confluent-kafka-go
go get github.com/hibiken/asynq
go get go.temporal.io/sdk

实用工具

使用脚本自动化设置:

  • Kafka 设置:运行 python scripts/kafka_producer_consumer.py 使用测试工具
  • 架构验证:运行 python scripts/validate_message_schema.py 验证事件架构

相关技能

  • api-patterns:用于异步作业提交的 API 设计
  • realtime-sync:用于作业状态更新的 WebSocket/SSE
  • feedback:用于作业完成的 Toast 通知
  • databases-*:用于事件日志的持久化存储
  • observability:用于队列操作的跟踪与指标

评论

支持 Markdown