fix(eslint): reduce warnings in GitHub Actions deployment
- Disable formatting rules (handled by Prettier) - Relaxed strict Vue/JS rules for demo code compatibility - Fix syntax errors in ApiPlayground and VoiceCloningDemo - Fix duplicate else-if condition in ApiPlayground - Fix Promise executor async pattern in AutoregressiveAudioDemo - Add TypeScript file support to ESLint config Warnings reduced from 295 to 251 problems. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,13 +29,22 @@
|
||||
|
||||
<div class="demo-content">
|
||||
<!-- 紧耦合模式 -->
|
||||
<div v-if="!useAsync" class="synchronous-mode">
|
||||
<div
|
||||
v-if="!useAsync"
|
||||
class="synchronous-mode"
|
||||
>
|
||||
<div class="scenario">
|
||||
<div class="scenario-title">❌ 紧耦合问题</div>
|
||||
<div class="scenario-title">
|
||||
❌ 紧耦合问题
|
||||
</div>
|
||||
<div class="flow-diagram">
|
||||
<div class="service-box order">
|
||||
<div class="service-name">订单服务</div>
|
||||
<div class="service-desc">创建订单</div>
|
||||
<div class="service-name">
|
||||
订单服务
|
||||
</div>
|
||||
<div class="service-desc">
|
||||
创建订单
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrows">
|
||||
@@ -45,9 +54,14 @@
|
||||
class="sync-call"
|
||||
:class="{ active: call.active }"
|
||||
>
|
||||
<div class="call-line"></div>
|
||||
<div class="call-label">{{ call.service }}</div>
|
||||
<div v-if="call.active" class="call-status">
|
||||
<div class="call-line" />
|
||||
<div class="call-label">
|
||||
{{ call.service }}
|
||||
</div>
|
||||
<div
|
||||
v-if="call.active"
|
||||
class="call-status"
|
||||
>
|
||||
{{ call.status }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -57,9 +71,18 @@
|
||||
class="service-box notification"
|
||||
:class="{ failed: notificationFailed }"
|
||||
>
|
||||
<div class="service-name">通知服务</div>
|
||||
<div class="service-desc">发送短信/邮件</div>
|
||||
<div v-if="notificationFailed" class="error-msg">服务宕机 ❌</div>
|
||||
<div class="service-name">
|
||||
通知服务
|
||||
</div>
|
||||
<div class="service-desc">
|
||||
发送短信/邮件
|
||||
</div>
|
||||
<div
|
||||
v-if="notificationFailed"
|
||||
class="error-msg"
|
||||
>
|
||||
服务宕机 ❌
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -70,10 +93,8 @@
|
||||
</div>
|
||||
<div class="problem-item">
|
||||
<span class="icon">⚠️</span>
|
||||
<span
|
||||
><strong>响应慢:</strong>总耗时 = 300ms + 500ms + 400ms =
|
||||
1200ms</span
|
||||
>
|
||||
<span><strong>响应慢:</strong>总耗时 = 300ms + 500ms + 400ms =
|
||||
1200ms</span>
|
||||
</div>
|
||||
<div class="problem-item">
|
||||
<span class="icon">⚠️</span>
|
||||
@@ -81,47 +102,81 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="test-btn fail" @click="testSyncCall">
|
||||
<button
|
||||
class="test-btn fail"
|
||||
@click="testSyncCall"
|
||||
>
|
||||
模拟通知服务故障
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 松耦合模式 -->
|
||||
<div v-else class="asynchronous-mode">
|
||||
<div
|
||||
v-else
|
||||
class="asynchronous-mode"
|
||||
>
|
||||
<div class="scenario">
|
||||
<div class="scenario-title">✅ 松耦合优势</div>
|
||||
<div class="scenario-title">
|
||||
✅ 松耦合优势
|
||||
</div>
|
||||
<div class="flow-diagram">
|
||||
<div class="service-box order">
|
||||
<div class="service-name">订单服务</div>
|
||||
<div class="service-desc">创建订单 + 发送消息</div>
|
||||
<div class="service-name">
|
||||
订单服务
|
||||
</div>
|
||||
<div class="service-desc">
|
||||
创建订单 + 发送消息
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mq-bridge">
|
||||
<div class="mq-box">
|
||||
<div class="mq-icon">📨</div>
|
||||
<div class="mq-label">消息队列</div>
|
||||
<div v-if="messageInQueue" class="msg-indicator">
|
||||
<div class="mq-icon">
|
||||
📨
|
||||
</div>
|
||||
<div class="mq-label">
|
||||
消息队列
|
||||
</div>
|
||||
<div
|
||||
v-if="messageInQueue"
|
||||
class="msg-indicator"
|
||||
>
|
||||
消息已发送
|
||||
</div>
|
||||
</div>
|
||||
<div class="flow-arrow">→</div>
|
||||
<div class="flow-arrow">
|
||||
→
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="consumers-group">
|
||||
<div class="consumer-box" :class="{ failed: consumerFailed }">
|
||||
<div class="consumer-name">短信服务</div>
|
||||
<div
|
||||
class="consumer-box"
|
||||
:class="{ failed: consumerFailed }"
|
||||
>
|
||||
<div class="consumer-name">
|
||||
短信服务
|
||||
</div>
|
||||
<div class="consumer-status">
|
||||
{{ consumerFailed ? '离线(不影响订单)' : '运行中' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="consumer-box">
|
||||
<div class="consumer-name">邮件服务</div>
|
||||
<div class="consumer-status">运行中</div>
|
||||
<div class="consumer-name">
|
||||
邮件服务
|
||||
</div>
|
||||
<div class="consumer-status">
|
||||
运行中
|
||||
</div>
|
||||
</div>
|
||||
<div class="consumer-box">
|
||||
<div class="consumer-name">积分服务</div>
|
||||
<div class="consumer-status">运行中</div>
|
||||
<div class="consumer-name">
|
||||
积分服务
|
||||
</div>
|
||||
<div class="consumer-status">
|
||||
运行中
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -133,9 +188,7 @@
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<span class="icon">✅</span>
|
||||
<span
|
||||
><strong>响应快:</strong>订单服务只耗时 50ms(发送消息)</span
|
||||
>
|
||||
<span><strong>响应快:</strong>订单服务只耗时 50ms(发送消息)</span>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<span class="icon">✅</span>
|
||||
@@ -143,7 +196,10 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="test-btn success" @click="testAsyncCall">
|
||||
<button
|
||||
class="test-btn success"
|
||||
@click="testAsyncCall"
|
||||
>
|
||||
发送订单消息
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -13,12 +13,24 @@
|
||||
<div class="controls">
|
||||
<div class="control">
|
||||
<label>失败率:</label>
|
||||
<input v-model.number="failureRate" type="range" min="0" max="100" step="10" />
|
||||
<input
|
||||
v-model.number="failureRate"
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
step="10"
|
||||
>
|
||||
<span class="value">{{ failureRate }}%</span>
|
||||
</div>
|
||||
<div class="control">
|
||||
<label>最大重试:</label>
|
||||
<input v-model.number="maxRetries" type="range" min="1" max="5" step="1" />
|
||||
<input
|
||||
v-model.number="maxRetries"
|
||||
type="range"
|
||||
min="1"
|
||||
max="5"
|
||||
step="1"
|
||||
>
|
||||
<span class="value">{{ maxRetries }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -26,7 +38,9 @@
|
||||
<div class="demo-content">
|
||||
<div class="flow-container">
|
||||
<div class="main-queue-section">
|
||||
<div class="section-title">📦 主队列</div>
|
||||
<div class="section-title">
|
||||
📦 主队列
|
||||
</div>
|
||||
<div class="queue-box main-queue">
|
||||
<div class="queue-header">
|
||||
<span>正常消息队列</span>
|
||||
@@ -39,42 +53,73 @@
|
||||
class="message-item"
|
||||
:class="{ processing: msg.processing }"
|
||||
>
|
||||
<div class="msg-id">#{{ msg.id }}</div>
|
||||
<div class="msg-retries" v-if="msg.retries > 0">
|
||||
<div class="msg-id">
|
||||
#{{ msg.id }}
|
||||
</div>
|
||||
<div
|
||||
v-if="msg.retries > 0"
|
||||
class="msg-retries"
|
||||
>
|
||||
重试: {{ msg.retries }}/{{ maxRetries }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="mainQueue.length === 0" class="empty">队列为空</div>
|
||||
<div v-else-if="mainQueue.length > 3" class="more">
|
||||
<div
|
||||
v-if="mainQueue.length === 0"
|
||||
class="empty"
|
||||
>
|
||||
队列为空
|
||||
</div>
|
||||
<div
|
||||
v-else-if="mainQueue.length > 3"
|
||||
class="more"
|
||||
>
|
||||
还有 {{ mainQueue.length - 3 }} 条...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="add-btn" @click="addMessage" :disabled="processing">
|
||||
<button
|
||||
class="add-btn"
|
||||
:disabled="processing"
|
||||
@click="addMessage"
|
||||
>
|
||||
+ 添加消息
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="processing-section">
|
||||
<div class="section-title">⚙️ 消费处理</div>
|
||||
<div class="section-title">
|
||||
⚙️ 消费处理
|
||||
</div>
|
||||
<div class="processor-box">
|
||||
<div class="processor-icon" :class="{ active: processing }">
|
||||
<div
|
||||
class="processor-icon"
|
||||
:class="{ active: processing }"
|
||||
>
|
||||
{{ processing ? '⚙️' : '💤' }}
|
||||
</div>
|
||||
<div class="processor-status">
|
||||
{{ processing ? '处理中...' : '空闲' }}
|
||||
</div>
|
||||
<div v-if="currentMessage" class="current-msg">
|
||||
<div
|
||||
v-if="currentMessage"
|
||||
class="current-msg"
|
||||
>
|
||||
处理: #{{ currentMessage.id }}
|
||||
</div>
|
||||
<div v-if="lastResult" class="last-result" :class="lastResult.type">
|
||||
<div
|
||||
v-if="lastResult"
|
||||
class="last-result"
|
||||
:class="lastResult.type"
|
||||
>
|
||||
{{ lastResult.message }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dlq-section">
|
||||
<div class="section-title">⚠️ 死信队列</div>
|
||||
<div class="section-title">
|
||||
⚠️ 死信队列
|
||||
</div>
|
||||
<div class="queue-box dead-letter">
|
||||
<div class="queue-header">
|
||||
<span>失败消息</span>
|
||||
@@ -86,21 +131,31 @@
|
||||
:key="msg.id"
|
||||
class="message-item failed"
|
||||
>
|
||||
<div class="msg-id">#{{ msg.id }}</div>
|
||||
<div class="msg-error">{{ msg.error }}</div>
|
||||
<div class="msg-id">
|
||||
#{{ msg.id }}
|
||||
</div>
|
||||
<div class="msg-error">
|
||||
{{ msg.error }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="deadLetterQueue.length === 0" class="empty">
|
||||
<div
|
||||
v-if="deadLetterQueue.length === 0"
|
||||
class="empty"
|
||||
>
|
||||
无失败消息
|
||||
</div>
|
||||
<div v-else-if="deadLetterQueue.length > 2" class="more">
|
||||
<div
|
||||
v-else-if="deadLetterQueue.length > 2"
|
||||
class="more"
|
||||
>
|
||||
还有 {{ deadLetterQueue.length - 2 }} 条...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="retry-btn"
|
||||
@click="retryDeadLetters"
|
||||
:disabled="deadLetterQueue.length === 0"
|
||||
@click="retryDeadLetters"
|
||||
>
|
||||
🔄 重试死信
|
||||
</button>
|
||||
@@ -109,20 +164,36 @@
|
||||
|
||||
<div class="stats">
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">总消息数</div>
|
||||
<div class="stat-value">{{ totalMessages }}</div>
|
||||
<div class="stat-label">
|
||||
总消息数
|
||||
</div>
|
||||
<div class="stat-value">
|
||||
{{ totalMessages }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card success">
|
||||
<div class="stat-label">成功处理</div>
|
||||
<div class="stat-value">{{ successCount }}</div>
|
||||
<div class="stat-label">
|
||||
成功处理
|
||||
</div>
|
||||
<div class="stat-value">
|
||||
{{ successCount }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card warning">
|
||||
<div class="stat-label">进入死信</div>
|
||||
<div class="stat-value">{{ deadLetterCount }}</div>
|
||||
<div class="stat-label">
|
||||
进入死信
|
||||
</div>
|
||||
<div class="stat-value">
|
||||
{{ deadLetterCount }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-label">成功率</div>
|
||||
<div class="stat-value">{{ successRate }}%</div>
|
||||
<div class="stat-label">
|
||||
成功率
|
||||
</div>
|
||||
<div class="stat-value">
|
||||
{{ successRate }}%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,13 +29,22 @@
|
||||
|
||||
<div class="demo-content">
|
||||
<!-- 紧耦合模式 -->
|
||||
<div v-if="!useAsync" class="synchronous-mode">
|
||||
<div
|
||||
v-if="!useAsync"
|
||||
class="synchronous-mode"
|
||||
>
|
||||
<div class="scenario">
|
||||
<div class="scenario-title">❌ 紧耦合的致命问题</div>
|
||||
<div class="scenario-title">
|
||||
❌ 紧耦合的致命问题
|
||||
</div>
|
||||
<div class="flow-diagram">
|
||||
<div class="service-box order">
|
||||
<div class="service-name">订单服务</div>
|
||||
<div class="service-desc">创建订单</div>
|
||||
<div class="service-name">
|
||||
订单服务
|
||||
</div>
|
||||
<div class="service-desc">
|
||||
创建订单
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrows">
|
||||
@@ -45,9 +54,14 @@
|
||||
class="sync-call"
|
||||
:class="{ active: call.active }"
|
||||
>
|
||||
<div class="call-line"></div>
|
||||
<div class="call-label">{{ call.service }}</div>
|
||||
<div v-if="call.active" class="call-status">
|
||||
<div class="call-line" />
|
||||
<div class="call-label">
|
||||
{{ call.service }}
|
||||
</div>
|
||||
<div
|
||||
v-if="call.active"
|
||||
class="call-status"
|
||||
>
|
||||
{{ call.status }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -57,9 +71,16 @@
|
||||
class="service-box notification"
|
||||
:class="{ failed: notificationFailed }"
|
||||
>
|
||||
<div class="service-name">通知服务</div>
|
||||
<div class="service-desc">发送短信/邮件</div>
|
||||
<div v-if="notificationFailed" class="error-msg">
|
||||
<div class="service-name">
|
||||
通知服务
|
||||
</div>
|
||||
<div class="service-desc">
|
||||
发送短信/邮件
|
||||
</div>
|
||||
<div
|
||||
v-if="notificationFailed"
|
||||
class="error-msg"
|
||||
>
|
||||
服务宕机 ❌
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,66 +89,94 @@
|
||||
<div class="problem-list">
|
||||
<div class="problem-item">
|
||||
<span class="icon">⚠️</span>
|
||||
<span
|
||||
><strong>依赖性强:</strong>通知服务宕机,订单创建失败</span
|
||||
>
|
||||
<span><strong>依赖性强:</strong>通知服务宕机,订单创建失败</span>
|
||||
</div>
|
||||
<div class="problem-item">
|
||||
<span class="icon">⚠️</span>
|
||||
<span
|
||||
><strong>响应慢:</strong>总耗时 = 300ms + 500ms + 400ms =
|
||||
1200ms</span
|
||||
>
|
||||
<span><strong>响应慢:</strong>总耗时 = 300ms + 500ms + 400ms =
|
||||
1200ms</span>
|
||||
</div>
|
||||
<div class="problem-item">
|
||||
<span class="icon">⚠️</span>
|
||||
<span
|
||||
><strong>扩展难:</strong>增加新服务需要修改订单代码</span
|
||||
>
|
||||
<span><strong>扩展难:</strong>增加新服务需要修改订单代码</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="test-btn fail" @click="testSyncCall">
|
||||
<button
|
||||
class="test-btn fail"
|
||||
@click="testSyncCall"
|
||||
>
|
||||
模拟通知服务故障
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 松耦合模式 -->
|
||||
<div v-else class="asynchronous-mode">
|
||||
<div
|
||||
v-else
|
||||
class="asynchronous-mode"
|
||||
>
|
||||
<div class="scenario">
|
||||
<div class="scenario-title">✅ 松耦合的核心优势</div>
|
||||
<div class="scenario-title">
|
||||
✅ 松耦合的核心优势
|
||||
</div>
|
||||
<div class="flow-diagram">
|
||||
<div class="service-box order">
|
||||
<div class="service-name">订单服务</div>
|
||||
<div class="service-desc">创建订单 + 发送消息</div>
|
||||
<div class="service-name">
|
||||
订单服务
|
||||
</div>
|
||||
<div class="service-desc">
|
||||
创建订单 + 发送消息
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mq-bridge">
|
||||
<div class="mq-box">
|
||||
<div class="mq-icon">📨</div>
|
||||
<div class="mq-label">消息队列</div>
|
||||
<div v-if="messageInQueue" class="msg-indicator">
|
||||
<div class="mq-icon">
|
||||
📨
|
||||
</div>
|
||||
<div class="mq-label">
|
||||
消息队列
|
||||
</div>
|
||||
<div
|
||||
v-if="messageInQueue"
|
||||
class="msg-indicator"
|
||||
>
|
||||
消息已发送
|
||||
</div>
|
||||
</div>
|
||||
<div class="flow-arrow">→</div>
|
||||
<div class="flow-arrow">
|
||||
→
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="consumers-group">
|
||||
<div class="consumer-box" :class="{ failed: consumerFailed }">
|
||||
<div class="consumer-name">短信服务</div>
|
||||
<div
|
||||
class="consumer-box"
|
||||
:class="{ failed: consumerFailed }"
|
||||
>
|
||||
<div class="consumer-name">
|
||||
短信服务
|
||||
</div>
|
||||
<div class="consumer-status">
|
||||
{{ consumerFailed ? '离线(不影响订单)' : '运行中' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="consumer-box">
|
||||
<div class="consumer-name">邮件服务</div>
|
||||
<div class="consumer-status">运行中</div>
|
||||
<div class="consumer-name">
|
||||
邮件服务
|
||||
</div>
|
||||
<div class="consumer-status">
|
||||
运行中
|
||||
</div>
|
||||
</div>
|
||||
<div class="consumer-box">
|
||||
<div class="consumer-name">积分服务</div>
|
||||
<div class="consumer-status">运行中</div>
|
||||
<div class="consumer-name">
|
||||
积分服务
|
||||
</div>
|
||||
<div class="consumer-status">
|
||||
运行中
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -135,25 +184,22 @@
|
||||
<div class="benefit-list">
|
||||
<div class="benefit-item">
|
||||
<span class="icon">✅</span>
|
||||
<span
|
||||
><strong>独立运行:</strong>通知服务宕机不影响订单创建</span
|
||||
>
|
||||
<span><strong>独立运行:</strong>通知服务宕机不影响订单创建</span>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<span class="icon">✅</span>
|
||||
<span
|
||||
><strong>响应快:</strong>订单服务只耗时 50ms(发送消息)</span
|
||||
>
|
||||
<span><strong>响应快:</strong>订单服务只耗时 50ms(发送消息)</span>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<span class="icon">✅</span>
|
||||
<span
|
||||
><strong>易扩展:</strong>增加新消费者无需修改订单代码</span
|
||||
>
|
||||
<span><strong>易扩展:</strong>增加新消费者无需修改订单代码</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="test-btn success" @click="testAsyncCall">
|
||||
<button
|
||||
class="test-btn success"
|
||||
@click="testAsyncCall"
|
||||
>
|
||||
发送订单消息
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -5,8 +5,12 @@
|
||||
<template>
|
||||
<div class="delayed-message-demo">
|
||||
<div class="header">
|
||||
<div class="title">延迟消息:让消息"定时送达"</div>
|
||||
<div class="subtitle">实现订单超时取消、定时提醒等功能</div>
|
||||
<div class="title">
|
||||
延迟消息:让消息"定时送达"
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
实现订单超时取消、定时提醒等功能
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="scenarios">
|
||||
@@ -23,10 +27,16 @@
|
||||
|
||||
<div class="demo-area">
|
||||
<div class="sender-section">
|
||||
<div class="section-title">📤 发送延迟消息</div>
|
||||
<div class="section-title">
|
||||
📤 发送延迟消息
|
||||
</div>
|
||||
<div class="scenario-info">
|
||||
<div class="scenario-name">{{ currentScenario.name }}</div>
|
||||
<div class="scenario-desc">{{ currentScenario.description }}</div>
|
||||
<div class="scenario-name">
|
||||
{{ currentScenario.name }}
|
||||
</div>
|
||||
<div class="scenario-desc">
|
||||
{{ currentScenario.description }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="delay-setting">
|
||||
@@ -43,25 +53,34 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="delay-custom">
|
||||
<input v-model="customDelay" type="number" min="1" max="3600" />
|
||||
<input
|
||||
v-model="customDelay"
|
||||
type="number"
|
||||
min="1"
|
||||
max="3600"
|
||||
>
|
||||
<span>秒</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="send-btn"
|
||||
@click="sendDelayedMessage"
|
||||
:disabled="sending"
|
||||
@click="sendDelayedMessage"
|
||||
>
|
||||
{{ sending ? '发送中...' : '📨 发送延迟消息' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="timeline-section">
|
||||
<div class="section-title">⏰ 延迟队列时间轴</div>
|
||||
<div class="section-title">
|
||||
⏰ 延迟队列时间轴
|
||||
</div>
|
||||
<div class="timeline">
|
||||
<div class="timeline-now">
|
||||
<div class="now-marker">现在</div>
|
||||
<div class="now-marker">
|
||||
现在
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="delayed-messages">
|
||||
@@ -72,29 +91,44 @@
|
||||
:style="{ left: msg.position + '%' }"
|
||||
>
|
||||
<div class="msg-bubble">
|
||||
<div class="msg-id">#{{ msg.id }}</div>
|
||||
<div class="msg-time">{{ msg.remaining }}s 后</div>
|
||||
<div class="msg-id">
|
||||
#{{ msg.id }}
|
||||
</div>
|
||||
<div class="msg-time">
|
||||
{{ msg.remaining }}s 后
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="msg-timer"
|
||||
:style="{ height: msg.timerHeight + '%' }"
|
||||
></div>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="timeline-scale">
|
||||
<div v-for="tick in timelineTicks" :key="tick" class="tick">
|
||||
<div class="tick-line"></div>
|
||||
<div class="tick-label">{{ tick }}s</div>
|
||||
<div
|
||||
v-for="tick in timelineTicks"
|
||||
:key="tick"
|
||||
class="tick"
|
||||
>
|
||||
<div class="tick-line" />
|
||||
<div class="tick-label">
|
||||
{{ tick }}s
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="result-section">
|
||||
<div class="section-title">📥 到期消息</div>
|
||||
<div class="section-title">
|
||||
📥 到期消息
|
||||
</div>
|
||||
<div class="result-box">
|
||||
<div v-if="deliveredMessages.length === 0" class="empty">
|
||||
<div
|
||||
v-if="deliveredMessages.length === 0"
|
||||
class="empty"
|
||||
>
|
||||
等待消息到期...
|
||||
</div>
|
||||
<div
|
||||
@@ -106,40 +140,70 @@
|
||||
<span class="msg-id">#{{ msg.id }}</span>
|
||||
<span class="msg-time">{{ msg.deliveredAt }}</span>
|
||||
</div>
|
||||
<div class="msg-content">{{ msg.content }}</div>
|
||||
<div class="msg-content">
|
||||
{{ msg.content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="use-cases">
|
||||
<div class="cases-title">💡 典型应用场景</div>
|
||||
<div class="cases-title">
|
||||
💡 典型应用场景
|
||||
</div>
|
||||
<div class="cases-grid">
|
||||
<div class="case-card">
|
||||
<div class="case-icon">🛒</div>
|
||||
<div class="case-name">订单超时取消</div>
|
||||
<div class="case-desc">下单后 30 分钟未支付,自动取消订单</div>
|
||||
<div class="case-icon">
|
||||
🛒
|
||||
</div>
|
||||
<div class="case-name">
|
||||
订单超时取消
|
||||
</div>
|
||||
<div class="case-desc">
|
||||
下单后 30 分钟未支付,自动取消订单
|
||||
</div>
|
||||
</div>
|
||||
<div class="case-card">
|
||||
<div class="case-icon">🔔</div>
|
||||
<div class="case-name">定时提醒</div>
|
||||
<div class="case-desc">会议开始前 15 分钟,发送提醒通知</div>
|
||||
<div class="case-icon">
|
||||
🔔
|
||||
</div>
|
||||
<div class="case-name">
|
||||
定时提醒
|
||||
</div>
|
||||
<div class="case-desc">
|
||||
会议开始前 15 分钟,发送提醒通知
|
||||
</div>
|
||||
</div>
|
||||
<div class="case-card">
|
||||
<div class="case-icon">🎁</div>
|
||||
<div class="case-name">会员过期提醒</div>
|
||||
<div class="case-desc">会员到期前 3 天,发送续费提醒</div>
|
||||
<div class="case-icon">
|
||||
🎁
|
||||
</div>
|
||||
<div class="case-name">
|
||||
会员过期提醒
|
||||
</div>
|
||||
<div class="case-desc">
|
||||
会员到期前 3 天,发送续费提醒
|
||||
</div>
|
||||
</div>
|
||||
<div class="case-card">
|
||||
<div class="case-icon">📊</div>
|
||||
<div class="case-name">数据统计</div>
|
||||
<div class="case-desc">每天凌晨 2 点,统计前一天的日报数据</div>
|
||||
<div class="case-icon">
|
||||
📊
|
||||
</div>
|
||||
<div class="case-name">
|
||||
数据统计
|
||||
</div>
|
||||
<div class="case-desc">
|
||||
每天凌晨 2 点,统计前一天的日报数据
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="implementation">
|
||||
<div class="impl-title">🔧 实现方式对比</div>
|
||||
<div class="impl-title">
|
||||
🔧 实现方式对比
|
||||
</div>
|
||||
<div class="impl-table">
|
||||
<table>
|
||||
<thead>
|
||||
|
||||
@@ -29,32 +29,55 @@
|
||||
|
||||
<div class="demo-content">
|
||||
<!-- 银行转账场景 -->
|
||||
<div v-if="scenario === 'transfer'" class="transfer-scenario">
|
||||
<div
|
||||
v-if="scenario === 'transfer'"
|
||||
class="transfer-scenario"
|
||||
>
|
||||
<div class="scenario-header">
|
||||
<div class="title">❌ 非幂等操作: 银行转账</div>
|
||||
<div class="subtitle">重复消费会导致多次扣款</div>
|
||||
<div class="title">
|
||||
❌ 非幂等操作: 银行转账
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
重复消费会导致多次扣款
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="account-system">
|
||||
<div class="account-card sender">
|
||||
<div class="account-name">发送方</div>
|
||||
<div class="account-name">
|
||||
发送方
|
||||
</div>
|
||||
<div class="account-balance">
|
||||
余额: ¥<span class="balance-amount">{{ senderBalance }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="transfer-flow">
|
||||
<div class="flow-animation" :class="{ active: isTransferring }">
|
||||
<div class="money-icon">💰</div>
|
||||
<div class="flow-label">转账 ¥100</div>
|
||||
<div
|
||||
class="flow-animation"
|
||||
:class="{ active: isTransferring }"
|
||||
>
|
||||
<div class="money-icon">
|
||||
💰
|
||||
</div>
|
||||
<div class="flow-label">
|
||||
转账 ¥100
|
||||
</div>
|
||||
</div>
|
||||
<div class="retry-info" v-if="retryCount > 0">
|
||||
<div class="retry-badge">重试 {{ retryCount }} 次</div>
|
||||
<div
|
||||
v-if="retryCount > 0"
|
||||
class="retry-info"
|
||||
>
|
||||
<div class="retry-badge">
|
||||
重试 {{ retryCount }} 次
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="account-card receiver">
|
||||
<div class="account-name">接收方</div>
|
||||
<div class="account-name">
|
||||
接收方
|
||||
</div>
|
||||
<div class="account-balance">
|
||||
余额: ¥<span class="balance-amount">{{ receiverBalance }}</span>
|
||||
</div>
|
||||
@@ -71,7 +94,7 @@
|
||||
:class="{ active: useIdempotence }"
|
||||
@click="useIdempotence = !useIdempotence"
|
||||
>
|
||||
<span class="toggle-slider"></span>
|
||||
<span class="toggle-slider" />
|
||||
</button>
|
||||
<span class="toggle-label">{{ useIdempotence ? '已启用' : '未启用' }}</span>
|
||||
</div>
|
||||
@@ -79,14 +102,17 @@
|
||||
|
||||
<button
|
||||
class="action-btn"
|
||||
@click="simulateTransfer"
|
||||
:disabled="isTransferring"
|
||||
@click="simulateTransfer"
|
||||
>
|
||||
{{ isTransferring ? '处理中...' : '模拟重复消费' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="idempotence-info" v-if="useIdempotence">
|
||||
<div
|
||||
v-if="useIdempotence"
|
||||
class="idempotence-info"
|
||||
>
|
||||
<div class="info-item">
|
||||
<span class="info-icon">🔑</span>
|
||||
<span class="info-text">每笔交易有唯一ID,重复请求被自动过滤</span>
|
||||
@@ -95,7 +121,9 @@
|
||||
</div>
|
||||
|
||||
<div class="result-log">
|
||||
<div class="log-header">处理日志</div>
|
||||
<div class="log-header">
|
||||
处理日志
|
||||
</div>
|
||||
<div class="log-list">
|
||||
<div
|
||||
v-for="(log, index) in logs"
|
||||
@@ -106,7 +134,10 @@
|
||||
<span class="log-time">{{ log.time }}</span>
|
||||
<span class="log-message">{{ log.message }}</span>
|
||||
</div>
|
||||
<div v-if="logs.length === 0" class="log-empty">
|
||||
<div
|
||||
v-if="logs.length === 0"
|
||||
class="log-empty"
|
||||
>
|
||||
暂无日志,点击按钮开始模拟
|
||||
</div>
|
||||
</div>
|
||||
@@ -114,32 +145,53 @@
|
||||
|
||||
<div class="comparison-box">
|
||||
<div class="comparison-item bad">
|
||||
<div class="comp-header">❌ 无幂等保护</div>
|
||||
<div class="comp-header">
|
||||
❌ 无幂等保护
|
||||
</div>
|
||||
<div class="comp-body">
|
||||
<div class="comp-result">扣款 ¥{{ (retryCount + 1) * 100 }}</div>
|
||||
<div class="comp-desc">重复消费造成多次扣款</div>
|
||||
<div class="comp-result">
|
||||
扣款 ¥{{ (retryCount + 1) * 100 }}
|
||||
</div>
|
||||
<div class="comp-desc">
|
||||
重复消费造成多次扣款
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="comparison-item good">
|
||||
<div class="comp-header">✅ 有幂等保护</div>
|
||||
<div class="comp-header">
|
||||
✅ 有幂等保护
|
||||
</div>
|
||||
<div class="comp-body">
|
||||
<div class="comp-result">扣款 ¥100</div>
|
||||
<div class="comp-desc">重复请求被过滤,只扣一次</div>
|
||||
<div class="comp-result">
|
||||
扣款 ¥100
|
||||
</div>
|
||||
<div class="comp-desc">
|
||||
重复请求被过滤,只扣一次
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 电梯按钮场景 -->
|
||||
<div v-else class="elevator-scenario">
|
||||
<div
|
||||
v-else
|
||||
class="elevator-scenario"
|
||||
>
|
||||
<div class="scenario-header">
|
||||
<div class="title">✅ 天然幂等操作: 电梯按钮</div>
|
||||
<div class="subtitle">无论按多少次,电梯只响应一次</div>
|
||||
<div class="title">
|
||||
✅ 天然幂等操作: 电梯按钮
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
无论按多少次,电梯只响应一次
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="elevator-system">
|
||||
<div class="elevator-panel">
|
||||
<div class="panel-title">电梯按钮面板</div>
|
||||
<div class="panel-title">
|
||||
电梯按钮面板
|
||||
</div>
|
||||
<div class="button-grid">
|
||||
<button
|
||||
v-for="floor in floors"
|
||||
@@ -169,8 +221,13 @@
|
||||
<span class="floor-num">{{ floor }}F</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="elevator-car" :style="{ bottom: elevatorPosition }">
|
||||
<div class="car-icon">🛗</div>
|
||||
<div
|
||||
class="elevator-car"
|
||||
:style="{ bottom: elevatorPosition }"
|
||||
>
|
||||
<div class="car-icon">
|
||||
🛗
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -178,7 +235,10 @@
|
||||
<div class="control-panel">
|
||||
<div class="control-item">
|
||||
<label>快速连按3次</label>
|
||||
<button class="action-btn" @click="pressMultipleTimes">
|
||||
<button
|
||||
class="action-btn"
|
||||
@click="pressMultipleTimes"
|
||||
>
|
||||
🚀 连续点击
|
||||
</button>
|
||||
</div>
|
||||
@@ -189,7 +249,9 @@
|
||||
</div>
|
||||
|
||||
<div class="explanation-box">
|
||||
<div class="explanation-title">为什么电梯按钮是幂等的?</div>
|
||||
<div class="explanation-title">
|
||||
为什么电梯按钮是幂等的?
|
||||
</div>
|
||||
<div class="explanation-list">
|
||||
<div class="explanation-item">
|
||||
<span class="icon">✅</span>
|
||||
@@ -209,7 +271,9 @@
|
||||
</div>
|
||||
|
||||
<div class="principle-box">
|
||||
<div class="principle-icon">🎯</div>
|
||||
<div class="principle-icon">
|
||||
🎯
|
||||
</div>
|
||||
<div class="principle-content">
|
||||
<strong>幂等性核心原则:</strong>
|
||||
{{ scenario === 'transfer'
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
<div class="demo-container">
|
||||
<div class="demo-header">
|
||||
<h4>{{ title }}</h4>
|
||||
<p class="hint">{{ description }}</p>
|
||||
<p class="hint">
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="demo-content">
|
||||
<el-alert type="info" :closable="false">
|
||||
<el-alert
|
||||
type="info"
|
||||
:closable="false"
|
||||
>
|
||||
消息队列架构演示组件占位符 - 待实现具体交互
|
||||
</el-alert>
|
||||
</div>
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
<div class="demo-container">
|
||||
<div class="demo-header">
|
||||
<h4>{{ title }}</h4>
|
||||
<p class="hint">{{ description }}</p>
|
||||
<p class="hint">
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="demo-content">
|
||||
<el-alert type="info" :closable="false">
|
||||
<el-alert
|
||||
type="info"
|
||||
:closable="false"
|
||||
>
|
||||
消息队列对比演示组件占位符 - 待实现具体交互
|
||||
</el-alert>
|
||||
</div>
|
||||
|
||||
+83
-27
@@ -5,8 +5,12 @@
|
||||
<template>
|
||||
<div class="mq-comparison-demo">
|
||||
<div class="header">
|
||||
<div class="title">主流消息队列对比</div>
|
||||
<div class="subtitle">选择不同 MQ,查看特性对比和适用场景</div>
|
||||
<div class="title">
|
||||
主流消息队列对比
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
选择不同 MQ,查看特性对比和适用场景
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mq-selector">
|
||||
@@ -24,48 +28,74 @@
|
||||
<div class="mq-details">
|
||||
<div class="mq-card">
|
||||
<div class="mq-header">
|
||||
<div class="mq-name">{{ currentMQ.label }}</div>
|
||||
<div class="mq-tag">{{ currentMQ.positioning }}</div>
|
||||
<div class="mq-name">
|
||||
{{ currentMQ.label }}
|
||||
</div>
|
||||
<div class="mq-tag">
|
||||
{{ currentMQ.positioning }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="metrics-grid">
|
||||
<div class="metric">
|
||||
<div class="metric-label">吞吐量</div>
|
||||
<div class="metric-value">{{ currentMQ.throughput }}</div>
|
||||
<div class="metric-label">
|
||||
吞吐量
|
||||
</div>
|
||||
<div class="metric-value">
|
||||
{{ currentMQ.throughput }}
|
||||
</div>
|
||||
<div class="metric-bar">
|
||||
<div
|
||||
class="bar-fill"
|
||||
:style="{ width: currentMQ.throughputPercent + '%' }"
|
||||
></div>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="metric">
|
||||
<div class="metric-label">延迟</div>
|
||||
<div class="metric-value">{{ currentMQ.latency }}</div>
|
||||
<div class="metric-desc">{{ currentMQ.latencyDesc }}</div>
|
||||
<div class="metric-label">
|
||||
延迟
|
||||
</div>
|
||||
<div class="metric-value">
|
||||
{{ currentMQ.latency }}
|
||||
</div>
|
||||
<div class="metric-desc">
|
||||
{{ currentMQ.latencyDesc }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="metric">
|
||||
<div class="metric-label">可靠性</div>
|
||||
<div class="metric-value">{{ currentMQ.reliability }}</div>
|
||||
<div class="metric-desc">{{ currentMQ.reliabilityDesc }}</div>
|
||||
<div class="metric-label">
|
||||
可靠性
|
||||
</div>
|
||||
<div class="metric-value">
|
||||
{{ currentMQ.reliability }}
|
||||
</div>
|
||||
<div class="metric-desc">
|
||||
{{ currentMQ.reliabilityDesc }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="metric">
|
||||
<div class="metric-label">学习曲线</div>
|
||||
<div class="metric-value">{{ currentMQ.learning }}</div>
|
||||
<div class="metric-label">
|
||||
学习曲线
|
||||
</div>
|
||||
<div class="metric-value">
|
||||
{{ currentMQ.learning }}
|
||||
</div>
|
||||
<div class="metric-bar">
|
||||
<div
|
||||
class="bar-fill learning"
|
||||
:style="{ width: currentMQ.learningPercent + '%' }"
|
||||
></div>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="features">
|
||||
<div class="feature-title">核心特性</div>
|
||||
<div class="feature-title">
|
||||
核心特性
|
||||
</div>
|
||||
<div class="feature-list">
|
||||
<div
|
||||
v-for="feature in currentMQ.features"
|
||||
@@ -78,18 +108,28 @@
|
||||
</div>
|
||||
|
||||
<div class="use-cases">
|
||||
<div class="use-case-title">✅ 适用场景</div>
|
||||
<div class="use-case-title">
|
||||
✅ 适用场景
|
||||
</div>
|
||||
<ul class="use-case-list">
|
||||
<li v-for="useCase in currentMQ.useCases" :key="useCase">
|
||||
<li
|
||||
v-for="useCase in currentMQ.useCases"
|
||||
:key="useCase"
|
||||
>
|
||||
{{ useCase }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="not-recommended">
|
||||
<div class="not-title">⚠️ 不推荐场景</div>
|
||||
<div class="not-title">
|
||||
⚠️ 不推荐场景
|
||||
</div>
|
||||
<ul class="not-list">
|
||||
<li v-for="item in currentMQ.notRecommended" :key="item">
|
||||
<li
|
||||
v-for="item in currentMQ.notRecommended"
|
||||
:key="item"
|
||||
>
|
||||
{{ item }}
|
||||
</li>
|
||||
</ul>
|
||||
@@ -98,7 +138,9 @@
|
||||
</div>
|
||||
|
||||
<div class="comparison-table">
|
||||
<div class="table-title">快速对比表</div>
|
||||
<div class="table-title">
|
||||
快速对比表
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -168,23 +210,37 @@
|
||||
</div>
|
||||
|
||||
<div class="recommendation">
|
||||
<div class="rec-title">💡 选择建议</div>
|
||||
<div class="rec-title">
|
||||
💡 选择建议
|
||||
</div>
|
||||
<div class="rec-content">
|
||||
<div v-if="selectedMQ === 'rabbitmq'" class="rec-text">
|
||||
<div
|
||||
v-if="selectedMQ === 'rabbitmq'"
|
||||
class="rec-text"
|
||||
>
|
||||
<strong>RabbitMQ</strong>
|
||||
是最稳妥的选择,适合大多数传统业务场景。如果团队有 AMQP
|
||||
经验,或者需要复杂的路由规则,优先选择它。
|
||||
</div>
|
||||
<div v-else-if="selectedMQ === 'kafka'" class="rec-text">
|
||||
<div
|
||||
v-else-if="selectedMQ === 'kafka'"
|
||||
class="rec-text"
|
||||
>
|
||||
<strong>Kafka</strong> 适合大数据量和流式处理场景。如果需要处理百万级
|
||||
TPS,或者需要消息回溯、与大数据生态集成,选择 Kafka。
|
||||
</div>
|
||||
<div v-else-if="selectedMQ === 'rocketmq'" class="rec-text">
|
||||
<div
|
||||
v-else-if="selectedMQ === 'rocketmq'"
|
||||
class="rec-text"
|
||||
>
|
||||
<strong>RocketMQ</strong>
|
||||
是阿里开源,特别适合电商、金融场景。如果需要事务消息、顺序消息、延迟消息等高级特性,RocketMQ
|
||||
是最佳选择。
|
||||
</div>
|
||||
<div v-else class="rec-text">
|
||||
<div
|
||||
v-else
|
||||
class="rec-text"
|
||||
>
|
||||
<strong>Redis Stream</strong> 最轻量,适合小团队和 MVP
|
||||
验证。如果已经有 Redis 基础设施,且对可靠性要求不是极高,可以先用
|
||||
Redis Stream 快速实现。
|
||||
|
||||
+132
-44
@@ -5,43 +5,68 @@
|
||||
<template>
|
||||
<div class="mq-components-demo">
|
||||
<div class="header">
|
||||
<div class="title">消息队列的三要素</div>
|
||||
<div class="subtitle">生产者、消息代理、消费者的关系</div>
|
||||
<div class="title">
|
||||
消息队列的三要素
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
生产者、消息代理、消费者的关系
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="components-flow">
|
||||
<div class="component producer">
|
||||
<div class="comp-header">
|
||||
<div class="comp-icon">📤</div>
|
||||
<div class="comp-name">生产者 Producer</div>
|
||||
<div class="comp-icon">
|
||||
📤
|
||||
</div>
|
||||
<div class="comp-name">
|
||||
生产者 Producer
|
||||
</div>
|
||||
</div>
|
||||
<div class="comp-content">
|
||||
<div class="comp-desc">发送消息的一方</div>
|
||||
<div class="comp-example">例子:订单服务</div>
|
||||
<div class="comp-desc">
|
||||
发送消息的一方
|
||||
</div>
|
||||
<div class="comp-example">
|
||||
例子:订单服务
|
||||
</div>
|
||||
<button
|
||||
class="action-btn"
|
||||
@click="produceMessage"
|
||||
:disabled="producing"
|
||||
@click="produceMessage"
|
||||
>
|
||||
{{ producing ? '发送中...' : '发送消息' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow" :class="{ active: messageInTransit }">
|
||||
<div
|
||||
class="arrow"
|
||||
:class="{ active: messageInTransit }"
|
||||
>
|
||||
{{ messageInTransit ? '📨' : '→' }}
|
||||
</div>
|
||||
|
||||
<div class="component broker">
|
||||
<div class="comp-header">
|
||||
<div class="comp-icon">📦</div>
|
||||
<div class="comp-name">消息代理 Broker</div>
|
||||
<div class="comp-icon">
|
||||
📦
|
||||
</div>
|
||||
<div class="comp-name">
|
||||
消息代理 Broker
|
||||
</div>
|
||||
</div>
|
||||
<div class="comp-content">
|
||||
<div class="comp-desc">存储和转发消息</div>
|
||||
<div class="comp-example">例子:RabbitMQ, Kafka</div>
|
||||
<div class="comp-desc">
|
||||
存储和转发消息
|
||||
</div>
|
||||
<div class="comp-example">
|
||||
例子:RabbitMQ, Kafka
|
||||
</div>
|
||||
<div class="broker-storage">
|
||||
<div class="storage-label">消息存储</div>
|
||||
<div class="storage-label">
|
||||
消息存储
|
||||
</div>
|
||||
<div class="storage-box">
|
||||
<transition-group name="message">
|
||||
<div
|
||||
@@ -52,7 +77,10 @@
|
||||
消息 #{{ msg.id }}
|
||||
</div>
|
||||
</transition-group>
|
||||
<div v-if="brokerMessages.length === 0" class="empty">
|
||||
<div
|
||||
v-if="brokerMessages.length === 0"
|
||||
class="empty"
|
||||
>
|
||||
暂无消息
|
||||
</div>
|
||||
</div>
|
||||
@@ -60,26 +88,40 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow" :class="{ active: consuming }">
|
||||
<div
|
||||
class="arrow"
|
||||
:class="{ active: consuming }"
|
||||
>
|
||||
{{ consuming ? '📨' : '→' }}
|
||||
</div>
|
||||
|
||||
<div class="component consumer">
|
||||
<div class="comp-header">
|
||||
<div class="comp-icon">📥</div>
|
||||
<div class="comp-name">消费者 Consumer</div>
|
||||
<div class="comp-icon">
|
||||
📥
|
||||
</div>
|
||||
<div class="comp-name">
|
||||
消费者 Consumer
|
||||
</div>
|
||||
</div>
|
||||
<div class="comp-content">
|
||||
<div class="comp-desc">接收并处理消息</div>
|
||||
<div class="comp-example">例子:库存服务</div>
|
||||
<div class="comp-desc">
|
||||
接收并处理消息
|
||||
</div>
|
||||
<div class="comp-example">
|
||||
例子:库存服务
|
||||
</div>
|
||||
<button
|
||||
class="action-btn consume"
|
||||
@click="consumeMessage"
|
||||
:disabled="brokerMessages.length === 0 || consuming"
|
||||
@click="consumeMessage"
|
||||
>
|
||||
{{ consuming ? '处理中...' : '消费消息' }}
|
||||
</button>
|
||||
<div v-if="lastConsumed" class="last-consumed">
|
||||
<div
|
||||
v-if="lastConsumed"
|
||||
class="last-consumed"
|
||||
>
|
||||
已处理: #{{ lastConsumed }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -88,7 +130,9 @@
|
||||
|
||||
<div class="component-details">
|
||||
<div class="detail-card producer">
|
||||
<div class="detail-title">📤 生产者 (Producer)</div>
|
||||
<div class="detail-title">
|
||||
📤 生产者 (Producer)
|
||||
</div>
|
||||
<div class="detail-content">
|
||||
<div class="detail-item">
|
||||
<strong>职责:</strong>创建并发送消息到 Broker
|
||||
@@ -108,7 +152,9 @@
|
||||
</div>
|
||||
|
||||
<div class="detail-card broker">
|
||||
<div class="detail-title">📦 消息代理 (Broker)</div>
|
||||
<div class="detail-title">
|
||||
📦 消息代理 (Broker)
|
||||
</div>
|
||||
<div class="detail-content">
|
||||
<div class="detail-item">
|
||||
<strong>职责:</strong>存储、转发、管理消息
|
||||
@@ -129,7 +175,9 @@
|
||||
</div>
|
||||
|
||||
<div class="detail-card consumer">
|
||||
<div class="detail-title">📥 消费者 (Consumer)</div>
|
||||
<div class="detail-title">
|
||||
📥 消费者 (Consumer)
|
||||
</div>
|
||||
<div class="detail-content">
|
||||
<div class="detail-item">
|
||||
<strong>职责:</strong>从 Broker 接收并处理消息
|
||||
@@ -155,45 +203,85 @@
|
||||
</div>
|
||||
|
||||
<div class="message-flow">
|
||||
<div class="flow-title">🔄 完整的消息流程</div>
|
||||
<div class="flow-title">
|
||||
🔄 完整的消息流程
|
||||
</div>
|
||||
<div class="flow-steps">
|
||||
<div class="flow-step">
|
||||
<div class="step-num">1</div>
|
||||
<div class="step-num">
|
||||
1
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<div class="step-title">生产者发送消息</div>
|
||||
<div class="step-desc">订单服务创建订单后,发送"订单创建"消息</div>
|
||||
<div class="step-title">
|
||||
生产者发送消息
|
||||
</div>
|
||||
<div class="step-desc">
|
||||
订单服务创建订单后,发送"订单创建"消息
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flow-arrow">→</div>
|
||||
<div class="flow-arrow">
|
||||
→
|
||||
</div>
|
||||
<div class="flow-step">
|
||||
<div class="step-num">2</div>
|
||||
<div class="step-num">
|
||||
2
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<div class="step-title">Broker 存储消息</div>
|
||||
<div class="step-desc">消息队列接收并存储消息(持久化到磁盘)</div>
|
||||
<div class="step-title">
|
||||
Broker 存储消息
|
||||
</div>
|
||||
<div class="step-desc">
|
||||
消息队列接收并存储消息(持久化到磁盘)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flow-arrow">→</div>
|
||||
<div class="flow-arrow">
|
||||
→
|
||||
</div>
|
||||
<div class="flow-step">
|
||||
<div class="step-num">3</div>
|
||||
<div class="step-num">
|
||||
3
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<div class="step-title">消费者拉取消息</div>
|
||||
<div class="step-desc">库存服务从队列中拉取消息</div>
|
||||
<div class="step-title">
|
||||
消费者拉取消息
|
||||
</div>
|
||||
<div class="step-desc">
|
||||
库存服务从队列中拉取消息
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flow-arrow">→</div>
|
||||
<div class="flow-arrow">
|
||||
→
|
||||
</div>
|
||||
<div class="flow-step">
|
||||
<div class="step-num">4</div>
|
||||
<div class="step-num">
|
||||
4
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<div class="step-title">处理业务逻辑</div>
|
||||
<div class="step-desc">扣减库存,创建出库记录</div>
|
||||
<div class="step-title">
|
||||
处理业务逻辑
|
||||
</div>
|
||||
<div class="step-desc">
|
||||
扣减库存,创建出库记录
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flow-arrow">→</div>
|
||||
<div class="flow-arrow">
|
||||
→
|
||||
</div>
|
||||
<div class="flow-step">
|
||||
<div class="step-num">5</div>
|
||||
<div class="step-num">
|
||||
5
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<div class="step-title">发送 ACK</div>
|
||||
<div class="step-desc">告诉 Broker 消息处理成功,可以删除</div>
|
||||
<div class="step-title">
|
||||
发送 ACK
|
||||
</div>
|
||||
<div class="step-desc">
|
||||
告诉 Broker 消息处理成功,可以删除
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,26 +5,44 @@
|
||||
<template>
|
||||
<div class="mq-demo">
|
||||
<div class="header">
|
||||
<div class="title">消息队列:异步通信的"缓冲器"</div>
|
||||
<div class="subtitle">观察消息如何通过队列实现异步处理</div>
|
||||
<div class="title">
|
||||
消息队列:异步通信的"缓冲器"
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
观察消息如何通过队列实现异步处理
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flow-container">
|
||||
<div class="section producer">
|
||||
<div class="section-title">生产者 Producer</div>
|
||||
<div class="box producer-box">
|
||||
<div class="icon">📤</div>
|
||||
<div class="label">订单服务</div>
|
||||
<div class="section-title">
|
||||
生产者 Producer
|
||||
</div>
|
||||
<button class="send-btn" @click="sendMessage" :disabled="sending">
|
||||
<div class="box producer-box">
|
||||
<div class="icon">
|
||||
📤
|
||||
</div>
|
||||
<div class="label">
|
||||
订单服务
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="send-btn"
|
||||
:disabled="sending"
|
||||
@click="sendMessage"
|
||||
>
|
||||
{{ sending ? '发送中...' : '发送消息' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="section broker">
|
||||
<div class="section-title">消息代理 Broker</div>
|
||||
<div class="section-title">
|
||||
消息代理 Broker
|
||||
</div>
|
||||
<div class="queue-container">
|
||||
<div class="queue-label">消息队列 Queue</div>
|
||||
<div class="queue-label">
|
||||
消息队列 Queue
|
||||
</div>
|
||||
<div class="queue-box">
|
||||
<transition-group name="message">
|
||||
<div
|
||||
@@ -36,22 +54,43 @@
|
||||
#{{ msg.id }}
|
||||
</div>
|
||||
</transition-group>
|
||||
<div v-if="messages.length === 0" class="empty-queue">队列为空</div>
|
||||
<div
|
||||
v-if="messages.length === 0"
|
||||
class="empty-queue"
|
||||
>
|
||||
队列为空
|
||||
</div>
|
||||
</div>
|
||||
<div class="queue-stats">
|
||||
<div class="stat">消息数: {{ messages.length }}</div>
|
||||
<div class="stat">容量: {{ queueCapacity }}</div>
|
||||
<div class="stat">
|
||||
消息数: {{ messages.length }}
|
||||
</div>
|
||||
<div class="stat">
|
||||
容量: {{ queueCapacity }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section consumer">
|
||||
<div class="section-title">消费者 Consumer</div>
|
||||
<div class="box consumer-box" :class="{ processing: isProcessing }">
|
||||
<div class="icon">{{ isProcessing ? '⚙️' : '📥' }}</div>
|
||||
<div class="label">{{ isProcessing ? '处理中...' : '库存服务' }}</div>
|
||||
<div class="section-title">
|
||||
消费者 Consumer
|
||||
</div>
|
||||
<div v-if="processedMessage" class="processed-msg">
|
||||
<div
|
||||
class="box consumer-box"
|
||||
:class="{ processing: isProcessing }"
|
||||
>
|
||||
<div class="icon">
|
||||
{{ isProcessing ? '⚙️' : '📥' }}
|
||||
</div>
|
||||
<div class="label">
|
||||
{{ isProcessing ? '处理中...' : '库存服务' }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="processedMessage"
|
||||
class="processed-msg"
|
||||
>
|
||||
已处理: #{{ processedMessage }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -60,41 +99,78 @@
|
||||
<div class="controls">
|
||||
<div class="control">
|
||||
<label>
|
||||
<input v-model="autoConsume" type="checkbox" />
|
||||
<input
|
||||
v-model="autoConsume"
|
||||
type="checkbox"
|
||||
>
|
||||
自动消费
|
||||
</label>
|
||||
</div>
|
||||
<div class="control">
|
||||
<label>
|
||||
<input v-model="showSync" type="checkbox" />
|
||||
<input
|
||||
v-model="showSync"
|
||||
type="checkbox"
|
||||
>
|
||||
显示同步对比
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="showSync" class="comparison">
|
||||
<div
|
||||
v-if="showSync"
|
||||
class="comparison"
|
||||
>
|
||||
<div class="compare-col sync">
|
||||
<div class="compare-title">同步调用 (Synchronous)</div>
|
||||
<div class="compare-flow">
|
||||
<div class="flow-item">A 调用 B</div>
|
||||
<div class="arrow">⬇️</div>
|
||||
<div class="flow-item wait">B 处理 (阻塞等待)</div>
|
||||
<div class="arrow">⬇️</div>
|
||||
<div class="flow-item">B 返回结果</div>
|
||||
<div class="compare-title">
|
||||
同步调用 (Synchronous)
|
||||
</div>
|
||||
<div class="compare-flow">
|
||||
<div class="flow-item">
|
||||
A 调用 B
|
||||
</div>
|
||||
<div class="arrow">
|
||||
⬇️
|
||||
</div>
|
||||
<div class="flow-item wait">
|
||||
B 处理 (阻塞等待)
|
||||
</div>
|
||||
<div class="arrow">
|
||||
⬇️
|
||||
</div>
|
||||
<div class="flow-item">
|
||||
B 返回结果
|
||||
</div>
|
||||
</div>
|
||||
<div class="compare-desc">
|
||||
总耗时 = 300ms + 500ms = 800ms
|
||||
</div>
|
||||
<div class="compare-desc">总耗时 = 300ms + 500ms = 800ms</div>
|
||||
</div>
|
||||
|
||||
<div class="compare-col async">
|
||||
<div class="compare-title">异步调用 (Asynchronous)</div>
|
||||
<div class="compare-flow">
|
||||
<div class="flow-item">A 发送消息</div>
|
||||
<div class="arrow">⬇️</div>
|
||||
<div class="flow-item highlight">消息队列缓冲</div>
|
||||
<div class="arrow">⬇️</div>
|
||||
<div class="flow-item">B 稍后处理</div>
|
||||
<div class="compare-title">
|
||||
异步调用 (Asynchronous)
|
||||
</div>
|
||||
<div class="compare-flow">
|
||||
<div class="flow-item">
|
||||
A 发送消息
|
||||
</div>
|
||||
<div class="arrow">
|
||||
⬇️
|
||||
</div>
|
||||
<div class="flow-item highlight">
|
||||
消息队列缓冲
|
||||
</div>
|
||||
<div class="arrow">
|
||||
⬇️
|
||||
</div>
|
||||
<div class="flow-item">
|
||||
B 稍后处理
|
||||
</div>
|
||||
</div>
|
||||
<div class="compare-desc">
|
||||
A 只需 10ms,B 在后台慢慢处理
|
||||
</div>
|
||||
<div class="compare-desc">A 只需 10ms,B 在后台慢慢处理</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,8 +5,12 @@
|
||||
<template>
|
||||
<div class="peak-shaving-demo">
|
||||
<div class="header">
|
||||
<div class="title">削峰填谷:把高峰"摊平"</div>
|
||||
<div class="subtitle">模拟流量突增场景,观察队列如何保护后端系统</div>
|
||||
<div class="title">
|
||||
削峰填谷:把高峰"摊平"
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
模拟流量突增场景,观察队列如何保护后端系统
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="main-layout">
|
||||
@@ -24,8 +28,10 @@
|
||||
max="1000"
|
||||
step="50"
|
||||
class="range-input process-range"
|
||||
/>
|
||||
<div class="desc">后端系统的最大处理速度</div>
|
||||
>
|
||||
<div class="desc">
|
||||
后端系统的最大处理速度
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
@@ -40,19 +46,24 @@
|
||||
max="10000"
|
||||
step="500"
|
||||
class="range-input queue-range"
|
||||
/>
|
||||
<div class="desc">消息队列能暂存的最大请求数</div>
|
||||
>
|
||||
<div class="desc">
|
||||
消息队列能暂存的最大请求数
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button
|
||||
class="action-btn burst-btn"
|
||||
@click="triggerBurst"
|
||||
:disabled="isBursting"
|
||||
@click="triggerBurst"
|
||||
>
|
||||
⚡️ 模拟秒杀流量突增
|
||||
</button>
|
||||
<button class="action-btn reset-btn" @click="reset">
|
||||
<button
|
||||
class="action-btn reset-btn"
|
||||
@click="reset"
|
||||
>
|
||||
🔄 重置系统
|
||||
</button>
|
||||
</div>
|
||||
@@ -63,13 +74,17 @@
|
||||
<!-- 状态指标卡片 -->
|
||||
<div class="metrics-grid">
|
||||
<div class="metric-item">
|
||||
<div class="m-label">当前入站流量</div>
|
||||
<div class="m-label">
|
||||
当前入站流量
|
||||
</div>
|
||||
<div class="m-value blue">
|
||||
{{ currentRequestRate }} <span class="unit">req/s</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric-item">
|
||||
<div class="m-label">队列积压量</div>
|
||||
<div class="m-label">
|
||||
队列积压量
|
||||
</div>
|
||||
<div class="m-value orange">
|
||||
{{ queueLength }} <span class="unit">msgs</span>
|
||||
</div>
|
||||
@@ -77,17 +92,21 @@
|
||||
<div
|
||||
class="m-bar-fill"
|
||||
:style="{ width: queuePercent + '%', background: queueColor }"
|
||||
></div>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric-item">
|
||||
<div class="m-label">实际处理速率</div>
|
||||
<div class="m-label">
|
||||
实际处理速率
|
||||
</div>
|
||||
<div class="m-value green">
|
||||
{{ currentProcessRate }} <span class="unit">req/s</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric-item">
|
||||
<div class="m-label">丢弃请求 (限流)</div>
|
||||
<div class="m-label">
|
||||
丢弃请求 (限流)
|
||||
</div>
|
||||
<div class="m-value red">
|
||||
{{ rejectedCount }} <span class="unit">req</span>
|
||||
</div>
|
||||
@@ -96,28 +115,28 @@
|
||||
|
||||
<!-- 实时图表 -->
|
||||
<div class="chart-container">
|
||||
<canvas ref="chartCanvas" width="600" height="200"></canvas>
|
||||
<canvas
|
||||
ref="chartCanvas"
|
||||
width="600"
|
||||
height="200"
|
||||
/>
|
||||
<div class="chart-legend">
|
||||
<span class="legend-item"
|
||||
><span class="dot blue"></span>入站流量 (用户请求)</span
|
||||
>
|
||||
<span class="legend-item"
|
||||
><span class="dot green"></span>处理流量 (系统负载)</span
|
||||
>
|
||||
<span class="legend-item"
|
||||
><span class="dot orange"></span>队列积压</span
|
||||
>
|
||||
<span class="legend-item"><span class="dot blue" />入站流量 (用户请求)</span>
|
||||
<span class="legend-item"><span class="dot green" />处理流量 (系统负载)</span>
|
||||
<span class="legend-item"><span class="dot orange" />队列积压</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="scenario-tips">
|
||||
<div class="tip-icon">💡</div>
|
||||
<div class="tip-icon">
|
||||
💡
|
||||
</div>
|
||||
<div class="tip-content">
|
||||
<strong>核心原理:</strong>
|
||||
当<strong>入站流量</strong>(蓝色)超过<strong>处理能力</strong>(绿色直线)时,多余的请求会被存入<strong>消息队列</strong>(橙色区域)。
|
||||
<br />
|
||||
<br>
|
||||
一旦流量高峰过去,系统会继续全速处理队列中的积压,直到队列清空。这就是"削峰填谷"。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+58
-21
@@ -5,8 +5,12 @@
|
||||
<template>
|
||||
<div class="messaging-patterns-demo">
|
||||
<div class="header">
|
||||
<div class="title">消息模式:点对点 vs 发布订阅</div>
|
||||
<div class="subtitle">选择模式,观察消息如何分发</div>
|
||||
<div class="title">
|
||||
消息模式:点对点 vs 发布订阅
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
选择模式,观察消息如何分发
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mode-selector">
|
||||
@@ -27,24 +31,38 @@
|
||||
</div>
|
||||
|
||||
<div class="description">
|
||||
<div v-if="mode === 'p2p'" class="desc-text">
|
||||
<strong>点对点模式:</strong
|
||||
>一条消息只能被<strong>一个消费者</strong>消费。适合任务分配、负载均衡场景。
|
||||
<div
|
||||
v-if="mode === 'p2p'"
|
||||
class="desc-text"
|
||||
>
|
||||
<strong>点对点模式:</strong>一条消息只能被<strong>一个消费者</strong>消费。适合任务分配、负载均衡场景。
|
||||
</div>
|
||||
<div v-else class="desc-text">
|
||||
<strong>发布订阅模式:</strong
|
||||
>一条消息可以被<strong>多个消费者</strong>同时接收。适合事件通知、广播场景。
|
||||
<div
|
||||
v-else
|
||||
class="desc-text"
|
||||
>
|
||||
<strong>发布订阅模式:</strong>一条消息可以被<strong>多个消费者</strong>同时接收。适合事件通知、广播场景。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="demo-area">
|
||||
<div class="producer-section">
|
||||
<div class="section-title">生产者 Producer</div>
|
||||
<div class="producer-box">
|
||||
<div class="icon">📤</div>
|
||||
<div class="label">订单服务</div>
|
||||
<div class="section-title">
|
||||
生产者 Producer
|
||||
</div>
|
||||
<button class="send-btn" @click="sendMessage" :disabled="sending">
|
||||
<div class="producer-box">
|
||||
<div class="icon">
|
||||
📤
|
||||
</div>
|
||||
<div class="label">
|
||||
订单服务
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="send-btn"
|
||||
:disabled="sending"
|
||||
@click="sendMessage"
|
||||
>
|
||||
{{ sending ? '发送中...' : '发送消息' }}
|
||||
</button>
|
||||
</div>
|
||||
@@ -54,11 +72,16 @@
|
||||
{{ mode === 'p2p' ? '队列 Queue' : '主题 Topic' }}
|
||||
</div>
|
||||
<div class="broker-box">
|
||||
<div class="broker-icon">{{ mode === 'p2p' ? '📦' : '📡' }}</div>
|
||||
<div class="broker-icon">
|
||||
{{ mode === 'p2p' ? '📦' : '📡' }}
|
||||
</div>
|
||||
<div class="broker-label">
|
||||
{{ mode === 'p2p' ? '消息队列' : '发布主题' }}
|
||||
</div>
|
||||
<div class="message-indicator" v-if="lastMessage">
|
||||
<div
|
||||
v-if="lastMessage"
|
||||
class="message-indicator"
|
||||
>
|
||||
消息 #{{ lastMessage }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,7 +91,9 @@
|
||||
</div>
|
||||
|
||||
<div class="consumer-section">
|
||||
<div class="section-title">消费者 Consumers</div>
|
||||
<div class="section-title">
|
||||
消费者 Consumers
|
||||
</div>
|
||||
<div class="consumers-grid">
|
||||
<div
|
||||
v-for="consumer in consumers"
|
||||
@@ -79,8 +104,12 @@
|
||||
<div class="consumer-icon">
|
||||
{{ consumer.active ? '⚙️' : '💤' }}
|
||||
</div>
|
||||
<div class="consumer-label">{{ consumer.name }}</div>
|
||||
<div class="consumer-count">已处理: {{ consumer.count }}</div>
|
||||
<div class="consumer-label">
|
||||
{{ consumer.name }}
|
||||
</div>
|
||||
<div class="consumer-count">
|
||||
已处理: {{ consumer.count }}
|
||||
</div>
|
||||
<div class="consumer-status">
|
||||
{{ consumer.active ? '处理中' : '空闲' }}
|
||||
</div>
|
||||
@@ -124,8 +153,13 @@
|
||||
</div>
|
||||
|
||||
<div class="example-scenario">
|
||||
<div class="scenario-title">📌 实际场景</div>
|
||||
<div v-if="mode === 'p2p'" class="scenario-content">
|
||||
<div class="scenario-title">
|
||||
📌 实际场景
|
||||
</div>
|
||||
<div
|
||||
v-if="mode === 'p2p'"
|
||||
class="scenario-content"
|
||||
>
|
||||
<div>
|
||||
<strong>任务分配:</strong>批量导入 10000 条用户数据,分发给 3
|
||||
个工作节点并行处理
|
||||
@@ -135,7 +169,10 @@
|
||||
每个任务只被处理一次
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="scenario-content">
|
||||
<div
|
||||
v-else
|
||||
class="scenario-content"
|
||||
>
|
||||
<div><strong>事件通知:</strong>用户下单成功后,同时通知多个系统</div>
|
||||
<div class="flow">
|
||||
发布事件 → [库存服务, 积分服务, 通知服务, 数据仓库] 各自独立处理
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
<div class="demo-container">
|
||||
<div class="demo-header">
|
||||
<h4>{{ title }}</h4>
|
||||
<p class="hint">{{ description }}</p>
|
||||
<p class="hint">
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="demo-content">
|
||||
<el-alert type="info" :closable="false">
|
||||
<el-alert
|
||||
type="info"
|
||||
:closable="false"
|
||||
>
|
||||
生产者消费者模式演示组件占位符 - 待实现具体交互
|
||||
</el-alert>
|
||||
</div>
|
||||
|
||||
@@ -5,46 +5,83 @@
|
||||
<template>
|
||||
<div class="pubsub-demo">
|
||||
<div class="header">
|
||||
<div class="title">发布订阅模式:一条消息,多处消费</div>
|
||||
<div class="subtitle">发布一次事件,多个订阅者独立处理</div>
|
||||
<div class="title">
|
||||
发布订阅模式:一条消息,多处消费
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
发布一次事件,多个订阅者独立处理
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="main-flow">
|
||||
<div class="publisher-section">
|
||||
<div class="section-title">📤 发布者 Publisher</div>
|
||||
<div class="section-title">
|
||||
📤 发布者 Publisher
|
||||
</div>
|
||||
<div class="event-selector">
|
||||
<label>选择事件:</label>
|
||||
<select v-model="selectedEvent" @change="onEventChange">
|
||||
<option value="order.created">订单创建成功</option>
|
||||
<option value="user.registered">用户注册成功</option>
|
||||
<option value="product.updated">商品信息更新</option>
|
||||
<select
|
||||
v-model="selectedEvent"
|
||||
@change="onEventChange"
|
||||
>
|
||||
<option value="order.created">
|
||||
订单创建成功
|
||||
</option>
|
||||
<option value="user.registered">
|
||||
用户注册成功
|
||||
</option>
|
||||
<option value="product.updated">
|
||||
商品信息更新
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="event-details">
|
||||
<div class="event-name">{{ eventDetails.name }}</div>
|
||||
<div class="event-desc">{{ eventDetails.description }}</div>
|
||||
<div class="event-name">
|
||||
{{ eventDetails.name }}
|
||||
</div>
|
||||
<div class="event-desc">
|
||||
{{ eventDetails.description }}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="publish-btn"
|
||||
@click="publishEvent"
|
||||
:disabled="publishing"
|
||||
@click="publishEvent"
|
||||
>
|
||||
{{ publishing ? '发布中...' : '🚀 发布事件' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="topic-section">
|
||||
<div class="section-title">📡 主题 Topic</div>
|
||||
<div class="topic-box" :class="{ active: hasMessage }">
|
||||
<div class="topic-icon">📨</div>
|
||||
<div class="topic-name">{{ selectedEvent }}</div>
|
||||
<div v-if="hasMessage" class="message-indicator">消息已发布</div>
|
||||
<div class="section-title">
|
||||
📡 主题 Topic
|
||||
</div>
|
||||
<div
|
||||
class="topic-box"
|
||||
:class="{ active: hasMessage }"
|
||||
>
|
||||
<div class="topic-icon">
|
||||
📨
|
||||
</div>
|
||||
<div class="topic-name">
|
||||
{{ selectedEvent }}
|
||||
</div>
|
||||
<div
|
||||
v-if="hasMessage"
|
||||
class="message-indicator"
|
||||
>
|
||||
消息已发布
|
||||
</div>
|
||||
</div>
|
||||
<div class="topic-desc">
|
||||
所有订阅者都会收到这条消息
|
||||
</div>
|
||||
<div class="topic-desc">所有订阅者都会收到这条消息</div>
|
||||
</div>
|
||||
|
||||
<div class="subscribers-section">
|
||||
<div class="section-title">📥 订阅者 Subscribers</div>
|
||||
<div class="section-title">
|
||||
📥 订阅者 Subscribers
|
||||
</div>
|
||||
<div class="subscribers-grid">
|
||||
<div
|
||||
v-for="sub in currentSubscribers"
|
||||
@@ -52,15 +89,23 @@
|
||||
class="subscriber-card"
|
||||
:class="{ processing: sub.processing, completed: sub.completed }"
|
||||
>
|
||||
<div class="sub-icon">{{ sub.icon }}</div>
|
||||
<div class="sub-name">{{ sub.name }}</div>
|
||||
<div class="sub-action">{{ sub.action }}</div>
|
||||
<div class="sub-icon">
|
||||
{{ sub.icon }}
|
||||
</div>
|
||||
<div class="sub-name">
|
||||
{{ sub.name }}
|
||||
</div>
|
||||
<div class="sub-action">
|
||||
{{ sub.action }}
|
||||
</div>
|
||||
<div class="sub-status">
|
||||
<span v-if="sub.processing">⏳ 处理中...</span>
|
||||
<span v-else-if="sub.completed">✅ 已完成</span>
|
||||
<span v-else>💤 等待消息</span>
|
||||
</div>
|
||||
<div class="sub-count">已处理: {{ sub.count }} 条</div>
|
||||
<div class="sub-count">
|
||||
已处理: {{ sub.count }} 条
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,11 +113,23 @@
|
||||
|
||||
<div class="real-time-log">
|
||||
<div class="log-header">
|
||||
<div class="log-title">📋 实时日志</div>
|
||||
<button class="clear-btn" @click="clearLog">清空</button>
|
||||
<div class="log-title">
|
||||
📋 实时日志
|
||||
</div>
|
||||
<button
|
||||
class="clear-btn"
|
||||
@click="clearLog"
|
||||
>
|
||||
清空
|
||||
</button>
|
||||
</div>
|
||||
<div class="log-content">
|
||||
<div v-if="logs.length === 0" class="log-empty">暂无日志</div>
|
||||
<div
|
||||
v-if="logs.length === 0"
|
||||
class="log-empty"
|
||||
>
|
||||
暂无日志
|
||||
</div>
|
||||
<div
|
||||
v-for="(log, index) in logs"
|
||||
:key="index"
|
||||
@@ -86,25 +143,39 @@
|
||||
</div>
|
||||
|
||||
<div class="use-cases">
|
||||
<div class="case-title">💡 典型应用场景</div>
|
||||
<div class="case-title">
|
||||
💡 典型应用场景
|
||||
</div>
|
||||
<div class="case-grid">
|
||||
<div class="case-card">
|
||||
<div class="case-icon">🛒</div>
|
||||
<div class="case-name">电商订单</div>
|
||||
<div class="case-icon">
|
||||
🛒
|
||||
</div>
|
||||
<div class="case-name">
|
||||
电商订单
|
||||
</div>
|
||||
<div class="case-desc">
|
||||
订单创建 → 库存服务、积分服务、通知服务、数据仓库同时处理
|
||||
</div>
|
||||
</div>
|
||||
<div class="case-card">
|
||||
<div class="case-icon">👤</div>
|
||||
<div class="case-name">用户注册</div>
|
||||
<div class="case-icon">
|
||||
👤
|
||||
</div>
|
||||
<div class="case-name">
|
||||
用户注册
|
||||
</div>
|
||||
<div class="case-desc">
|
||||
用户注册 → 欢迎邮件、短信验证、发放优惠券、创建用户画像
|
||||
</div>
|
||||
</div>
|
||||
<div class="case-card">
|
||||
<div class="case-icon">📊</div>
|
||||
<div class="case-name">数据分析</div>
|
||||
<div class="case-icon">
|
||||
📊
|
||||
</div>
|
||||
<div class="case-name">
|
||||
数据分析
|
||||
</div>
|
||||
<div class="case-desc">
|
||||
用户行为 → 推荐系统、实时统计、数据仓库、风控系统
|
||||
</div>
|
||||
|
||||
@@ -14,46 +14,86 @@
|
||||
<!-- 防线1: 生产者确认 -->
|
||||
<div class="defense-line">
|
||||
<div class="defense-header">
|
||||
<div class="defense-badge line1">防线 1</div>
|
||||
<div class="defense-title">生产者确认 (Producer ACK)</div>
|
||||
<div class="defense-badge line1">
|
||||
防线 1
|
||||
</div>
|
||||
<div class="defense-title">
|
||||
生产者确认 (Producer ACK)
|
||||
</div>
|
||||
</div>
|
||||
<div class="defense-content">
|
||||
<div class="flow-diagram">
|
||||
<div class="component producer">
|
||||
<div class="comp-icon">📤</div>
|
||||
<div class="comp-label">生产者</div>
|
||||
<div class="comp-desc">发送消息</div>
|
||||
<div class="comp-icon">
|
||||
📤
|
||||
</div>
|
||||
<div class="comp-label">
|
||||
生产者
|
||||
</div>
|
||||
<div class="comp-desc">
|
||||
发送消息
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="message-flow">
|
||||
<div class="msg-item" :class="{ active: step === 1 }">
|
||||
<div class="msg-icon">📨</div>
|
||||
<div class="msg-label">消息</div>
|
||||
<div v-if="step === 1" class="msg-status">
|
||||
<div
|
||||
class="msg-item"
|
||||
:class="{ active: step === 1 }"
|
||||
>
|
||||
<div class="msg-icon">
|
||||
📨
|
||||
</div>
|
||||
<div class="msg-label">
|
||||
消息
|
||||
</div>
|
||||
<div
|
||||
v-if="step === 1"
|
||||
class="msg-status"
|
||||
>
|
||||
{{ ackStatus }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ack-item" :class="{ active: step === 2 }">
|
||||
<div class="ack-icon">✓</div>
|
||||
<div class="ack-label">ACK确认</div>
|
||||
<div v-if="step === 2" class="ack-status">
|
||||
<div
|
||||
class="ack-item"
|
||||
:class="{ active: step === 2 }"
|
||||
>
|
||||
<div class="ack-icon">
|
||||
✓
|
||||
</div>
|
||||
<div class="ack-label">
|
||||
ACK确认
|
||||
</div>
|
||||
<div
|
||||
v-if="step === 2"
|
||||
class="ack-status"
|
||||
>
|
||||
{{ ackMessage }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="component broker">
|
||||
<div class="comp-icon">📦</div>
|
||||
<div class="comp-label">Broker</div>
|
||||
<div class="comp-desc">接收并存储</div>
|
||||
<div class="comp-icon">
|
||||
📦
|
||||
</div>
|
||||
<div class="comp-label">
|
||||
Broker
|
||||
</div>
|
||||
<div class="comp-desc">
|
||||
接收并存储
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-panel">
|
||||
<div class="control-item">
|
||||
<label>发送消息</label>
|
||||
<button class="action-btn" @click="sendWithAck" :disabled="step > 0">
|
||||
<button
|
||||
class="action-btn"
|
||||
:disabled="step > 0"
|
||||
@click="sendWithAck"
|
||||
>
|
||||
发送并等待确认
|
||||
</button>
|
||||
</div>
|
||||
@@ -68,26 +108,54 @@
|
||||
<!-- 防线2: Broker持久化 -->
|
||||
<div class="defense-line">
|
||||
<div class="defense-header">
|
||||
<div class="defense-badge line2">防线 2</div>
|
||||
<div class="defense-title">Broker持久化</div>
|
||||
<div class="defense-badge line2">
|
||||
防线 2
|
||||
</div>
|
||||
<div class="defense-title">
|
||||
Broker持久化
|
||||
</div>
|
||||
</div>
|
||||
<div class="defense-content">
|
||||
<div class="storage-diagram">
|
||||
<div class="storage-container">
|
||||
<div class="storage-option" :class="{ active: storageType === 'memory' }">
|
||||
<div class="option-icon">⚡</div>
|
||||
<div class="option-label">内存存储</div>
|
||||
<div class="option-desc">速度快,但重启丢失</div>
|
||||
<div class="option-risk">❌ 高风险</div>
|
||||
<div
|
||||
class="storage-option"
|
||||
:class="{ active: storageType === 'memory' }"
|
||||
>
|
||||
<div class="option-icon">
|
||||
⚡
|
||||
</div>
|
||||
<div class="option-label">
|
||||
内存存储
|
||||
</div>
|
||||
<div class="option-desc">
|
||||
速度快,但重启丢失
|
||||
</div>
|
||||
<div class="option-risk">
|
||||
❌ 高风险
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="vs-divider">vs</div>
|
||||
<div class="vs-divider">
|
||||
vs
|
||||
</div>
|
||||
|
||||
<div class="storage-option recommended" :class="{ active: storageType === 'disk' }">
|
||||
<div class="option-icon">💾</div>
|
||||
<div class="option-label">磁盘存储</div>
|
||||
<div class="option-desc">落盘保证不丢失</div>
|
||||
<div class="option-risk">✅ 推荐</div>
|
||||
<div
|
||||
class="storage-option recommended"
|
||||
:class="{ active: storageType === 'disk' }"
|
||||
>
|
||||
<div class="option-icon">
|
||||
💾
|
||||
</div>
|
||||
<div class="option-label">
|
||||
磁盘存储
|
||||
</div>
|
||||
<div class="option-desc">
|
||||
落盘保证不丢失
|
||||
</div>
|
||||
<div class="option-risk">
|
||||
✅ 推荐
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -122,7 +190,10 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-text" :class="{ warning: storageType === 'memory' }">
|
||||
<div
|
||||
class="info-text"
|
||||
:class="{ warning: storageType === 'memory' }"
|
||||
>
|
||||
<span class="info-icon">{{ storageType === 'disk' ? '✅' : '⚠️' }}</span>
|
||||
{{ storageType === 'disk' ? '消息已落盘,安全可靠' : '消息仅在内存,重启丢失' }}
|
||||
</div>
|
||||
@@ -133,58 +204,115 @@
|
||||
<!-- 防线3: 消费者确认 -->
|
||||
<div class="defense-line">
|
||||
<div class="defense-header">
|
||||
<div class="defense-badge line3">防线 3</div>
|
||||
<div class="defense-title">消费者确认 (Consumer ACK)</div>
|
||||
<div class="defense-badge line3">
|
||||
防线 3
|
||||
</div>
|
||||
<div class="defense-title">
|
||||
消费者确认 (Consumer ACK)
|
||||
</div>
|
||||
</div>
|
||||
<div class="defense-content">
|
||||
<div class="consumer-flow">
|
||||
<div class="flow-step" :class="{ active: consumerStep >= 1 }">
|
||||
<div class="step-num">1</div>
|
||||
<div
|
||||
class="flow-step"
|
||||
:class="{ active: consumerStep >= 1 }"
|
||||
>
|
||||
<div class="step-num">
|
||||
1
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<div class="step-title">拉取消息</div>
|
||||
<div class="step-desc">从Broker获取消息</div>
|
||||
<div class="step-title">
|
||||
拉取消息
|
||||
</div>
|
||||
<div class="step-desc">
|
||||
从Broker获取消息
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flow-arrow" :class="{ active: consumerStep >= 1 }">→</div>
|
||||
<div
|
||||
class="flow-arrow"
|
||||
:class="{ active: consumerStep >= 1 }"
|
||||
>
|
||||
→
|
||||
</div>
|
||||
|
||||
<div class="flow-step" :class="{ active: consumerStep >= 2 }">
|
||||
<div class="step-num">2</div>
|
||||
<div
|
||||
class="flow-step"
|
||||
:class="{ active: consumerStep >= 2 }"
|
||||
>
|
||||
<div class="step-num">
|
||||
2
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<div class="step-title">处理消息</div>
|
||||
<div class="step-desc">执行业务逻辑</div>
|
||||
<div class="step-title">
|
||||
处理消息
|
||||
</div>
|
||||
<div class="step-desc">
|
||||
执行业务逻辑
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flow-arrow" :class="{ active: consumerStep >= 2 }">→</div>
|
||||
<div
|
||||
class="flow-arrow"
|
||||
:class="{ active: consumerStep >= 2 }"
|
||||
>
|
||||
→
|
||||
</div>
|
||||
|
||||
<div class="flow-step" :class="{ active: consumerStep >= 3 }">
|
||||
<div class="step-num">3</div>
|
||||
<div
|
||||
class="flow-step"
|
||||
:class="{ active: consumerStep >= 3 }"
|
||||
>
|
||||
<div class="step-num">
|
||||
3
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<div class="step-title">手动ACK</div>
|
||||
<div class="step-desc">确认处理完成</div>
|
||||
<div class="step-title">
|
||||
手动ACK
|
||||
</div>
|
||||
<div class="step-desc">
|
||||
确认处理完成
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ack-comparison">
|
||||
<div class="ack-option">
|
||||
<div class="ack-type">自动 ACK</div>
|
||||
<div class="ack-desc">高效但可能丢消息</div>
|
||||
<div class="ack-risk">⚠️ 不推荐</div>
|
||||
<div class="ack-type">
|
||||
自动 ACK
|
||||
</div>
|
||||
<div class="ack-desc">
|
||||
高效但可能丢消息
|
||||
</div>
|
||||
<div class="ack-risk">
|
||||
⚠️ 不推荐
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ack-option recommended">
|
||||
<div class="ack-type">手动 ACK</div>
|
||||
<div class="ack-desc">可靠,处理完才确认</div>
|
||||
<div class="ack-risk">✅ 推荐</div>
|
||||
<div class="ack-type">
|
||||
手动 ACK
|
||||
</div>
|
||||
<div class="ack-desc">
|
||||
可靠,处理完才确认
|
||||
</div>
|
||||
<div class="ack-risk">
|
||||
✅ 推荐
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-panel">
|
||||
<div class="control-item">
|
||||
<label>模拟消费</label>
|
||||
<button class="action-btn" @click="simulateConsume" :disabled="consumerStep > 0">
|
||||
<button
|
||||
class="action-btn"
|
||||
:disabled="consumerStep > 0"
|
||||
@click="simulateConsume"
|
||||
>
|
||||
开始消费流程
|
||||
</button>
|
||||
</div>
|
||||
@@ -198,7 +326,9 @@
|
||||
</div>
|
||||
|
||||
<div class="summary-box">
|
||||
<div class="summary-icon">🎯</div>
|
||||
<div class="summary-icon">
|
||||
🎯
|
||||
</div>
|
||||
<div class="summary-content">
|
||||
<strong>三道防线,缺一不可:</strong>生产者确认 → Broker持久化 → 消费者确认
|
||||
</div>
|
||||
|
||||
@@ -5,8 +5,12 @@
|
||||
<template>
|
||||
<div class="seckill-demo">
|
||||
<div class="header">
|
||||
<div class="title">秒杀系统:消息队列的典型应用</div>
|
||||
<div class="subtitle">处理 10 万/秒的并发请求,保证不超卖</div>
|
||||
<div class="title">
|
||||
秒杀系统:消息队列的典型应用
|
||||
</div>
|
||||
<div class="subtitle">
|
||||
处理 10 万/秒的并发请求,保证不超卖
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="scenario-settings">
|
||||
@@ -16,7 +20,13 @@
|
||||
<strong>{{ stock }}</strong>
|
||||
件
|
||||
</label>
|
||||
<input v-model="stock" type="range" min="10" max="1000" step="10" />
|
||||
<input
|
||||
v-model="stock"
|
||||
type="range"
|
||||
min="10"
|
||||
max="1000"
|
||||
step="10"
|
||||
>
|
||||
</div>
|
||||
<div class="setting">
|
||||
<label>
|
||||
@@ -30,7 +40,7 @@
|
||||
min="100"
|
||||
max="10000"
|
||||
step="100"
|
||||
/>
|
||||
>
|
||||
</div>
|
||||
<div class="setting">
|
||||
<label>
|
||||
@@ -44,33 +54,52 @@
|
||||
min="50"
|
||||
max="500"
|
||||
step="10"
|
||||
/>
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="action-bar">
|
||||
<button class="start-btn" @click="startSeckill" :disabled="running">
|
||||
<button
|
||||
class="start-btn"
|
||||
:disabled="running"
|
||||
@click="startSeckill"
|
||||
>
|
||||
🚀 开始秒杀
|
||||
</button>
|
||||
<button class="reset-btn" @click="reset">🔄 重置</button>
|
||||
<button
|
||||
class="reset-btn"
|
||||
@click="reset"
|
||||
>
|
||||
🔄 重置
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="architecture">
|
||||
<div class="arch-layer gateway">
|
||||
<div class="layer-title">🌐 网关层 - 限流</div>
|
||||
<div class="layer-title">
|
||||
🌐 网关层 - 限流
|
||||
</div>
|
||||
<div class="layer-content">
|
||||
<div class="stat-box">
|
||||
<div class="stat-label">总请求数</div>
|
||||
<div class="stat-value">{{ totalRequests.toLocaleString() }}</div>
|
||||
<div class="stat-label">
|
||||
总请求数
|
||||
</div>
|
||||
<div class="stat-value">
|
||||
{{ totalRequests.toLocaleString() }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<div class="stat-label">限流通过</div>
|
||||
<div class="stat-label">
|
||||
限流通过
|
||||
</div>
|
||||
<div class="stat-value success">
|
||||
{{ passedRequests.toLocaleString() }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<div class="stat-label">被拒绝</div>
|
||||
<div class="stat-label">
|
||||
被拒绝
|
||||
</div>
|
||||
<div class="stat-value error">
|
||||
{{ rejectedRequests.toLocaleString() }}
|
||||
</div>
|
||||
@@ -78,32 +107,43 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arch-arrow">⬇️</div>
|
||||
<div class="arch-arrow">
|
||||
⬇️
|
||||
</div>
|
||||
|
||||
<div class="arch-layer redis">
|
||||
<div class="layer-title">⚡ Redis 预扣库存</div>
|
||||
<div class="layer-title">
|
||||
⚡ Redis 预扣库存
|
||||
</div>
|
||||
<div class="layer-content">
|
||||
<div class="stock-display">
|
||||
<div class="stock-bar">
|
||||
<div
|
||||
class="stock-fill"
|
||||
:style="{ width: stockPercent + '%' }"
|
||||
></div>
|
||||
/>
|
||||
</div>
|
||||
<div class="stock-text">
|
||||
剩余: {{ remainingStock }} / {{ stock }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="redis-status" :class="redisStatus.class">
|
||||
<div
|
||||
class="redis-status"
|
||||
:class="redisStatus.class"
|
||||
>
|
||||
{{ redisStatus.text }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arch-arrow">⬇️</div>
|
||||
<div class="arch-arrow">
|
||||
⬇️
|
||||
</div>
|
||||
|
||||
<div class="arch-layer queue">
|
||||
<div class="layer-title">📦 消息队列缓冲</div>
|
||||
<div class="layer-title">
|
||||
📦 消息队列缓冲
|
||||
</div>
|
||||
<div class="layer-content">
|
||||
<div class="queue-visual">
|
||||
<div class="queue-box">
|
||||
@@ -116,63 +156,109 @@
|
||||
class="queue-bar"
|
||||
:class="queueStatus"
|
||||
:style="{ width: queuePercent + '%' }"
|
||||
></div>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arch-arrow">⬇️</div>
|
||||
<div class="arch-arrow">
|
||||
⬇️
|
||||
</div>
|
||||
|
||||
<div class="arch-layer consumer">
|
||||
<div class="layer-title">⚙️ 订单服务处理</div>
|
||||
<div class="layer-title">
|
||||
⚙️ 订单服务处理
|
||||
</div>
|
||||
<div class="layer-content">
|
||||
<div class="stat-box">
|
||||
<div class="stat-label">处理中</div>
|
||||
<div class="stat-value">{{ processing }}</div>
|
||||
<div class="stat-label">
|
||||
处理中
|
||||
</div>
|
||||
<div class="stat-value">
|
||||
{{ processing }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<div class="stat-label">成功订单</div>
|
||||
<div class="stat-value success">{{ successOrders }}</div>
|
||||
<div class="stat-label">
|
||||
成功订单
|
||||
</div>
|
||||
<div class="stat-value success">
|
||||
{{ successOrders }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<div class="stat-label">失败订单</div>
|
||||
<div class="stat-value error">{{ failedOrders }}</div>
|
||||
<div class="stat-label">
|
||||
失败订单
|
||||
</div>
|
||||
<div class="stat-value error">
|
||||
{{ failedOrders }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="real-time-stats">
|
||||
<div class="stats-title">📊 实时监控</div>
|
||||
<div class="stats-title">
|
||||
📊 实时监控
|
||||
</div>
|
||||
<div class="stats-grid">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">平均响应时间</div>
|
||||
<div class="stat-value">{{ avgLatency }}ms</div>
|
||||
<div class="stat-label">
|
||||
平均响应时间
|
||||
</div>
|
||||
<div class="stat-value">
|
||||
{{ avgLatency }}ms
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">订单成功率</div>
|
||||
<div class="stat-value">{{ orderSuccessRate }}%</div>
|
||||
<div class="stat-label">
|
||||
订单成功率
|
||||
</div>
|
||||
<div class="stat-value">
|
||||
{{ orderSuccessRate }}%
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">队列积压</div>
|
||||
<div class="stat-value">{{ queueLength }}</div>
|
||||
<div class="stat-label">
|
||||
队列积压
|
||||
</div>
|
||||
<div class="stat-value">
|
||||
{{ queueLength }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">预计清空时间</div>
|
||||
<div class="stat-value">{{ estimatedTime }}</div>
|
||||
<div class="stat-label">
|
||||
预计清空时间
|
||||
</div>
|
||||
<div class="stat-value">
|
||||
{{ estimatedTime }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="log-section">
|
||||
<div class="log-header">
|
||||
<div class="log-title">📋 事件日志</div>
|
||||
<button class="clear-log" @click="clearLogs">清空</button>
|
||||
<div class="log-title">
|
||||
📋 事件日志
|
||||
</div>
|
||||
<button
|
||||
class="clear-log"
|
||||
@click="clearLogs"
|
||||
>
|
||||
清空
|
||||
</button>
|
||||
</div>
|
||||
<div class="log-content">
|
||||
<div v-if="logs.length === 0" class="log-empty">暂无日志</div>
|
||||
<div
|
||||
v-if="logs.length === 0"
|
||||
class="log-empty"
|
||||
>
|
||||
暂无日志
|
||||
</div>
|
||||
<div
|
||||
v-for="(log, index) in logs.slice(0, 15)"
|
||||
:key="index"
|
||||
@@ -186,7 +272,9 @@
|
||||
</div>
|
||||
|
||||
<div class="key-points">
|
||||
<div class="point-title">🎯 核心设计要点</div>
|
||||
<div class="point-title">
|
||||
🎯 核心设计要点
|
||||
</div>
|
||||
<div class="point-list">
|
||||
<div class="point-item">
|
||||
<span class="point-icon">1️⃣</span>
|
||||
@@ -198,22 +286,19 @@
|
||||
<div class="point-item">
|
||||
<span class="point-icon">2️⃣</span>
|
||||
<div>
|
||||
<strong>Redis 预扣:</strong
|
||||
>原子操作扣减库存,快速判断是否有货,避免无效请求
|
||||
<strong>Redis 预扣:</strong>原子操作扣减库存,快速判断是否有货,避免无效请求
|
||||
</div>
|
||||
</div>
|
||||
<div class="point-item">
|
||||
<span class="point-icon">3️⃣</span>
|
||||
<div>
|
||||
<strong>消息队列:</strong
|
||||
>将成功的扣库存请求放入队列,异步处理,削峰填谷
|
||||
<strong>消息队列:</strong>将成功的扣库存请求放入队列,异步处理,削峰填谷
|
||||
</div>
|
||||
</div>
|
||||
<div class="point-item">
|
||||
<span class="point-icon">4️⃣</span>
|
||||
<div>
|
||||
<strong>异步处理:</strong
|
||||
>订单服务慢慢消费队列,创建订单,保证不超卖
|
||||
<strong>异步处理:</strong>订单服务慢慢消费队列,创建订单,保证不超卖
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user