# mq **Repository Path**: middleware-lab/mq ## Basic Information - **Project Name**: mq - **Description**: 创建mq场景和使用 - **Primary Language**: Go - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-15 - **Last Updated**: 2026-09-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MQ 模拟实验室 一个用 **Go 后端 + React 前端** 构建的消息队列(MQ)演示项目。它用一个内存版的消息队列模拟器,把 MQ 中最常见的**使用场景、特性、以及实际会踩到的坑**以可视化的方式演示出来。 - 后端:Go 实现一个精简的 MQ(队列、投递、ACK/NACK、重试、死信、延迟消息、TTL、持久化/恢复),并通过 **REST + SSE(Server-Sent Events)** 把消息流转实时推送到前端。 - 前端:React + Vite + TypeScript,把场景列表、消息流转时间线、队列状态实时展示出来。 ## 运行环境 - Go 1.22+ - Node.js 18+ 与 npm ## 快速开始 ```bash # 1. 安装前端依赖 make install # 2. 一键启动前后端(两个终端分别运行亦可) ./dev.sh ``` 启动后访问 **http://localhost:5173**(如果 5173 被占用,Vite 会自动换到 5174,看终端提示)。 也可以分开启动: ```bash # 终端 1:后端(默认 18080 端口) make dev-backend # 终端 2:前端(默认 5173 端口,/api 自动代理到后端) make dev-frontend ``` ## 端口说明 | 服务 | 地址 | 说明 | | --- | --- | --- | | Go 后端 | `http://localhost:18080` | 可用环境变量 `PORT` 覆盖 | | React 前端 | `http://localhost:5173` | 开发服务器,`/api*` 代理到后端 | 前端默认通过 Vite 的 proxy 把 `/api` 转发到 `http://localhost:18080`(见 `frontend/vite.config.ts`)。 ## 使用方式 1. 打开首页,左侧列表按「使用场景 / 特性 / 常见问题」分了组。 2. **单击**场景卡片查看说明(问题场景会显示「问题」与「对策」)。 3. **双击**场景即可运行,右侧「消息流转」会实时滚动展示生产者/消费者的每一步动作,右下「队列状态」实时统计各队列的待消费 / 处理中 / 已投递 / 已确认 / 死信数量。 4. 页头显示当前运行场景,可随时点「停止」。 ## 内置场景(13 个) **使用场景** | ID | 名称 | 演示内容 | | --- | --- | --- | | `work-queue` | 工作队列 | 多个消费者竞争消费,一条消息只被一个消费者处理(负载均衡) | | `pubsub` | 发布/订阅 | 一条消息广播给所有订阅者,每个订阅者各得一份副本 | | `routing` | 消息路由 | 按路由键匹配 topic 规则(`*`、`#`)选择性分发 | | `rpc` | 请求/应答 | `reply-to` 回调队列 + `correlation-id` 实现基于消息的 RPC | | `delayed` | 延迟消息 | 消息在指定延迟后才对消费者可见 | **特性** | ID | 名称 | 演示内容 | | --- | --- | --- | | `retry-dlq` | 重试与死信 | 消费失败自动重试,重试耗尽进入死信队列(DLQ) | | `ttl` | 消息过期 (TTL) | 消息在指定时间内未消费则自动过期 | | `durability` | 持久化与手动确认 | 持久化队列 + 手动 ACK,消费者崩溃后消息可恢复 | | `dedup` | 幂等去重 | 重复投递时按消息 ID 幂等,只处理一次 | **常见问题(坑)** | ID | 名称 | 问题 / 对策 | | --- | --- | --- | | `message-loss` | 消息丢失 | 自动 ACK 过早确认 → 崩溃即丢失;对策:手动 ACK + 持久化 | | `duplicate` | 重复消费 | 至少一次投递 + 无幂等 → 重复扣款;对策:按唯一 ID 幂等 | | `ordering` | 顺序错乱 | 并发消费导致乱序;对策:单消费者 / 分区键 | | `backlog` | 消息堆积 | 生产远快于消费导致积压;对策:扩容 / 限流 / 削峰 | ## 架构 ``` 浏览器 (React) │ REST: /api/scenarios /api/scenarios/{id}/run /api/stats │ SSE: /api/events(实时事件流) ▼ Go 后端 (net/http,标准库实现,无第三方依赖) ├── server/ HTTP 路由、REST、SSE、CORS ├── scenario/ 场景引擎 + 13 个场景脚本 ├── broker/ 内存版消息队列模拟器 ├── sse/ 事件广播中心(订阅 + 历史回放) └── model/ 共享数据模型 ``` ## 目录结构 ``` mq/ ├── backend/ │ ├── go.mod │ ├── cmd/mqsim/main.go │ └── internal/ │ ├── model/ 模型与事件类型 │ ├── broker/ 消息队列模拟器 │ ├── scenario/ 场景引擎与场景实现(usage/features/pitfalls) │ ├── sse/ 事件广播 │ └── server/ HTTP API 与 SSE ├── frontend/ │ ├── src/ │ │ ├── App.tsx │ │ ├── api.ts REST/SSE 封装 │ │ ├── types.ts │ │ └── components/ 场景列表 / 事件流 / 队列统计 / 场景详情 │ ├── vite.config.ts /api 代理 │ └── package.json ├── dev.sh 一键启动 ├── Makefile └── README.md ``` ## API 一览 | 方法 | 路径 | 说明 | | --- | --- | --- | | GET | `/api/health` | 健康检查 | | GET | `/api/scenarios` | 场景列表(含是否运行中) | | POST | `/api/scenarios/{id}/run` | 运行指定场景 | | POST | `/api/scenarios/stop` | 停止当前场景 | | GET | `/api/stats` | 队列统计快照 | | GET | `/api/events` | SSE 实时事件流(含历史回放) | ## 新增一个场景 1. 在 `backend/internal/scenario/` 下(按类别放进 `usage.go` / `features.go` / `pitfalls.go`)编写一个形如 `func runXxx(ctx, b *broker.Broker, e emitFn)` 的函数。 2. 在 `scenario.go` 的 `AllScenarios()` 里注册它的元数据(ID、名称、分类、摘要,问题场景补 `problem`/`solution`)。 3. 前端会自动从 `/api/scenarios` 读取并渲染,无需改动。 ## 构建产物 ```bash make build # 后端 go build + 前端 npm run build ``` 前端产物输出到 `frontend/dist/`。