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:
sanbuphy
2026-02-18 17:38:10 +08:00
parent 8b01686e68
commit 0eba9e87e9
456 changed files with 28450 additions and 9677 deletions
@@ -5,82 +5,147 @@
<template>
<div class="api-gateway-demo">
<div class="header">
<div class="title">🚪 API 网关系统的"统一大门"</div>
<div class="subtitle">想象成写字楼的前台所有访客都要先经过这里才能到达不同的办公室</div>
<div class="title">
🚪 API 网关系统的"统一大门"
</div>
<div class="subtitle">
想象成写字楼的前台所有访客都要先经过这里才能到达不同的办公室
</div>
</div>
<div class="architecture-view">
<div class="layer client-layer">
<div class="layer-title">客户端 (来访者)</div>
<div class="layer-title">
客户端 (来访者)
</div>
<div class="clients">
<div class="client-item">📱 App</div>
<div class="client-item">💻 Web</div>
<div class="client-item">🔧 第三方</div>
<div class="client-item">
📱 App
</div>
<div class="client-item">
💻 Web
</div>
<div class="client-item">
🔧 第三方
</div>
</div>
</div>
<div class="arrow-down"> 统一入口</div>
<div class="arrow-down">
统一入口
</div>
<div class="layer gateway-layer">
<div class="layer-title">🚪 API 网关 (前台)</div>
<div class="layer-title">
🚪 API 网关 (前台)
</div>
<div class="gateway-box">
<div class="gateway-function" :class="{ active: activeFunc === 'auth' }" @click="setActive('auth')">
<div
class="gateway-function"
:class="{ active: activeFunc === 'auth' }"
@click="setActive('auth')"
>
<span class="func-icon">🔐</span>
<span class="func-name">身份认证</span>
</div>
<div class="gateway-function" :class="{ active: activeFunc === 'rate' }" @click="setActive('rate')">
<div
class="gateway-function"
:class="{ active: activeFunc === 'rate' }"
@click="setActive('rate')"
>
<span class="func-icon"></span>
<span class="func-name">限流熔断</span>
</div>
<div class="gateway-function" :class="{ active: activeFunc === 'route' }" @click="setActive('route')">
<div
class="gateway-function"
:class="{ active: activeFunc === 'route' }"
@click="setActive('route')"
>
<span class="func-icon">🧭</span>
<span class="func-name">路由转发</span>
</div>
<div class="gateway-function" :class="{ active: activeFunc === 'transform' }" @click="setActive('transform')">
<div
class="gateway-function"
:class="{ active: activeFunc === 'transform' }"
@click="setActive('transform')"
>
<span class="func-icon">🔄</span>
<span class="func-name">协议转换</span>
</div>
</div>
</div>
<div class="arrow-down"> 分发请求</div>
<div class="arrow-down">
分发请求
</div>
<div class="layer backend-layer">
<div class="layer-title"> 后端服务 (各个部门)</div>
<div class="layer-title">
后端服务 (各个部门)
</div>
<div class="services">
<div class="service-card">
<div class="service-icon">👤</div>
<div class="service-name">用户服务</div>
<div class="service-tech">/api/users</div>
<div class="service-icon">
👤
</div>
<div class="service-name">
用户服务
</div>
<div class="service-tech">
/api/users
</div>
</div>
<div class="service-card">
<div class="service-icon">📦</div>
<div class="service-name">订单服务</div>
<div class="service-tech">/api/orders</div>
<div class="service-icon">
📦
</div>
<div class="service-name">
订单服务
</div>
<div class="service-tech">
/api/orders
</div>
</div>
<div class="service-card">
<div class="service-icon">💳</div>
<div class="service-name">支付服务</div>
<div class="service-tech">/api/pay</div>
<div class="service-icon">
💳
</div>
<div class="service-name">
支付服务
</div>
<div class="service-tech">
/api/pay
</div>
</div>
</div>
</div>
</div>
<div class="function-detail" v-if="activeFunc">
<div
v-if="activeFunc"
class="function-detail"
>
<div class="detail-header">
<span class="detail-icon">{{ currentFunction.icon }}</span>
<span class="detail-name">{{ currentFunction.name }}</span>
</div>
<div class="detail-desc">{{ currentFunction.desc }}</div>
<div class="detail-desc">
{{ currentFunction.desc }}
</div>
<div class="detail-example">
<div class="example-title">💡 实际场景</div>
<div class="example-content">{{ currentFunction.example }}</div>
<div class="example-title">
💡 实际场景
</div>
<div class="example-content">
{{ currentFunction.example }}
</div>
</div>
</div>
<div class="comparison-table">
<div class="table-title">🤔 没有网关 vs 有网关的区别</div>
<div class="table-title">
🤔 没有网关 vs 有网关的区别
</div>
<table>
<thead>
<tr>
@@ -5,8 +5,12 @@
<template>
<div class="auth-middleware-demo">
<div class="header">
<div class="title">🔐 认证中间件谁可以进大门</div>
<div class="subtitle">想象成写字楼门禁检查工牌验证身份没权限的人进不来</div>
<div class="title">
🔐 认证中间件谁可以进大门
</div>
<div class="subtitle">
想象成写字楼门禁检查工牌验证身份没权限的人进不来
</div>
</div>
<div class="auth-tabs">
@@ -22,45 +26,91 @@
</div>
<div class="auth-flow">
<div class="flow-title">{{ currentAuthData.title }}</div>
<div class="flow-title">
{{ currentAuthData.title }}
</div>
<div class="flow-diagram">
<div class="flow-step" v-for="(step, index) in currentAuthData.steps" :key="index">
<div class="step-number">{{ index + 1 }}</div>
<div
v-for="(step, index) in currentAuthData.steps"
:key="index"
class="flow-step"
>
<div class="step-number">
{{ index + 1 }}
</div>
<div class="step-content">
<div class="step-actor">{{ step.actor }}</div>
<div class="step-action">{{ step.action }}</div>
<div class="step-arrow" v-if="index < currentAuthData.steps.length - 1"></div>
<div class="step-actor">
{{ step.actor }}
</div>
<div class="step-action">
{{ step.action }}
</div>
<div
v-if="index < currentAuthData.steps.length - 1"
class="step-arrow"
>
</div>
</div>
</div>
</div>
<div class="token-display" v-if="currentAuth === 'jwt'">
<div class="token-header">🔑 JWT Token 结构Base64编码</div>
<div
v-if="currentAuth === 'jwt'"
class="token-display"
>
<div class="token-header">
🔑 JWT Token 结构Base64编码
</div>
<div class="token-parts">
<div class="token-part header">
<div class="part-label">HEADER</div>
<div class="part-content">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9</div>
<div class="part-decoded">{ "alg": "HS256", "typ": "JWT" }</div>
<div class="part-label">
HEADER
</div>
<div class="part-content">
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
</div>
<div class="part-decoded">
{ "alg": "HS256", "typ": "JWT" }
</div>
</div>
<div class="token-separator">
.
</div>
<div class="token-separator">.</div>
<div class="token-part payload">
<div class="part-label">PAYLOAD</div>
<div class="part-content">eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ</div>
<div class="part-decoded">{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }</div>
<div class="part-label">
PAYLOAD
</div>
<div class="part-content">
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
</div>
<div class="part-decoded">
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
</div>
</div>
<div class="token-separator">
.
</div>
<div class="token-separator">.</div>
<div class="token-part signature">
<div class="part-label">SIGNATURE</div>
<div class="part-content">SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c</div>
<div class="part-decoded">HMACSHA256(base64Url(header) + "." + base64Url(payload), secret)</div>
<div class="part-label">
SIGNATURE
</div>
<div class="part-content">
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
</div>
<div class="part-decoded">
HMACSHA256(base64Url(header) + "." + base64Url(payload), secret)
</div>
</div>
</div>
</div>
</div>
<div class="implementation-comparison">
<div class="section-title">🛠 三种方案实现对比</div>
<div class="section-title">
🛠 三种方案实现对比
</div>
<table class="comparison-table">
<thead>
@@ -73,31 +123,41 @@
</thead>
<tbody>
<tr>
<td class="dim">存储位置</td>
<td class="dim">
存储位置
</td>
<td>服务端存储 Session客户端存 Cookie</td>
<td>客户端存储 Token服务端无状态</td>
<td>授权服务器存储客户端存 Access Token</td>
</tr>
<tr>
<td class="dim">扩展性</td>
<td class="dim">
扩展性
</td>
<td> 需要共享 Session扩展复杂</td>
<td> 无状态易于水平扩展</td>
<td> 分布式架构支持大规模系统</td>
</tr>
<tr>
<td class="dim">安全性</td>
<td class="dim">
安全性
</td>
<td> Cookie 可能被窃取需要 CSRF 防护</td>
<td> Token 泄露风险 HTTPS + 短期有效</td>
<td> 行业最佳实践支持多种安全机制</td>
</tr>
<tr>
<td class="dim">实现复杂度</td>
<td class="dim">
实现复杂度
</td>
<td>🟢 简单开箱即用</td>
<td>🟡 中等需要 Token 管理</td>
<td>🔴 复杂需要授权服务器</td>
</tr>
<tr>
<td class="dim">适用场景</td>
<td class="dim">
适用场景
</td>
<td>传统 Web 应用后台管理系统</td>
<td>SPA移动端 API微服务</td>
<td>第三方登录开放平台SSO</td>
@@ -107,34 +167,60 @@
</div>
<div class="security-tips">
<div class="tips-title">🔒 网关层认证最佳实践</div>
<div class="tips-title">
🔒 网关层认证最佳实践
</div>
<div class="tips-list">
<div class="tip-item">
<div class="tip-icon">1</div>
<div class="tip-icon">
1
</div>
<div class="tip-content">
<div class="tip-heading">统一在网关层验证</div>
<div class="tip-desc">不要在每个微服务里重复写认证逻辑统一在网关层校验 JWT Session</div>
<div class="tip-heading">
统一在网关层验证
</div>
<div class="tip-desc">
不要在每个微服务里重复写认证逻辑统一在网关层校验 JWT Session
</div>
</div>
</div>
<div class="tip-item">
<div class="tip-icon">2</div>
<div class="tip-icon">
2
</div>
<div class="tip-content">
<div class="tip-heading">HTTPS 强制</div>
<div class="tip-desc">网关层强制 HTTPS防止 Token 在传输过程中被窃取中间人攻击</div>
<div class="tip-heading">
HTTPS 强制
</div>
<div class="tip-desc">
网关层强制 HTTPS防止 Token 在传输过程中被窃取中间人攻击
</div>
</div>
</div>
<div class="tip-item">
<div class="tip-icon">3</div>
<div class="tip-icon">
3
</div>
<div class="tip-content">
<div class="tip-heading">Token 过期策略</div>
<div class="tip-desc">Access Token 短期有效15分钟配合 Refresh Token 实现无感知续期</div>
<div class="tip-heading">
Token 过期策略
</div>
<div class="tip-desc">
Access Token 短期有效15分钟配合 Refresh Token 实现无感知续期
</div>
</div>
</div>
<div class="tip-item">
<div class="tip-icon">4</div>
<div class="tip-icon">
4
</div>
<div class="tip-content">
<div class="tip-heading">黑名单机制</div>
<div class="tip-desc">用户登出或 Token 泄露时 Token 加入黑名单Redis 存储</div>
<div class="tip-heading">
黑名单机制
</div>
<div class="tip-desc">
用户登出或 Token 泄露时 Token 加入黑名单Redis 存储
</div>
</div>
</div>
</div>
@@ -5,12 +5,18 @@
<template>
<div class="load-balancing-demo">
<div class="header">
<div class="title"> 负载均衡"压力"均匀分摊到多台服务器</div>
<div class="subtitle">想象成银行的取号系统把客户均匀分配到各个窗口避免某个窗口排长队</div>
<div class="title">
负载均衡"压力"均匀分摊到多台服务器
</div>
<div class="subtitle">
想象成银行的取号系统把客户均匀分配到各个窗口避免某个窗口排长队
</div>
</div>
<div class="strategy-selector">
<div class="selector-title">选择负载均衡策略</div>
<div class="selector-title">
选择负载均衡策略
</div>
<div class="strategy-tabs">
<button
v-for="strategy in strategies"
@@ -20,36 +26,64 @@
>
<span class="tab-icon">{{ strategy.icon }}</span>
<span class="tab-name">{{ strategy.name }}</span>
<span class="tab-badge" v-if="strategy.badge">{{ strategy.badge }}</span>
<span
v-if="strategy.badge"
class="tab-badge"
>{{ strategy.badge }}</span>
</button>
</div>
</div>
<div class="simulation-area">
<div class="sim-header">
<div class="sim-title">🎮 负载均衡模拟器</div>
<div class="sim-title">
🎮 负载均衡模拟器
</div>
<div class="sim-controls">
<button class="sim-btn" @click="startSimulation" :disabled="isSimulating">
<button
class="sim-btn"
:disabled="isSimulating"
@click="startSimulation"
>
{{ isSimulating ? '运行中...' : '▶ 开始模拟' }}
</button>
<button class="sim-btn reset" @click="resetSimulation"> 重置</button>
<button
class="sim-btn reset"
@click="resetSimulation"
>
重置
</button>
</div>
</div>
<div class="strategy-explanation">
<div class="exp-icon">💡</div>
<div class="exp-icon">
💡
</div>
<div class="exp-content">
<div class="exp-title">{{ currentStrategyData.name }} - {{ currentStrategyData.shortDesc }}</div>
<div class="exp-desc">{{ currentStrategyData.fullDesc }}</div>
<div class="exp-title">
{{ currentStrategyData.name }} - {{ currentStrategyData.shortDesc }}
</div>
<div class="exp-desc">
{{ currentStrategyData.fullDesc }}
</div>
</div>
</div>
<div class="servers-pool">
<div class="pool-header">
<div class="pool-title">🏢 后端服务器集群</div>
<div class="pool-title">
🏢 后端服务器集群
</div>
<div class="pool-config">
<label>服务器数量:</label>
<input type="range" v-model="serverCount" min="2" max="6" :disabled="isSimulating" />
<input
v-model="serverCount"
type="range"
min="2"
max="6"
:disabled="isSimulating"
>
<span>{{ serverCount }} </span>
</div>
</div>
@@ -62,9 +96,16 @@
:style="{ borderColor: server.color }"
>
<div class="server-header">
<div class="server-icon">🖥</div>
<div class="server-name">{{ server.name }}</div>
<div class="server-status" :style="{ background: server.color }">
<div class="server-icon">
🖥
</div>
<div class="server-name">
{{ server.name }}
</div>
<div
class="server-status"
:style="{ background: server.color }"
>
{{ server.load }}%
</div>
</div>
@@ -78,23 +119,28 @@
<span class="metric-label">权重:</span>
<input
v-if="currentStrategy === 'weighted'"
type="number"
v-model.number="server.weight"
type="number"
min="1"
max="10"
:disabled="isSimulating"
class="weight-input"
/>
>
<span v-else>{{ server.weight }}</span>
</div>
</div>
<div class="load-bar">
<div class="load-fill" :style="{ width: server.load + '%', background: server.color }"></div>
<div
class="load-fill"
:style="{ width: server.load + '%', background: server.color }"
/>
</div>
<div class="recent-requests">
<div class="req-label">最近请求:</div>
<div class="req-label">
最近请求:
</div>
<div class="req-list">
<span
v-for="(req, idx) in server.recentRequests"
@@ -112,7 +158,9 @@
<div class="request-queue">
<div class="queue-header">
<div class="queue-title">📨 请求队列</div>
<div class="queue-title">
📨 请求队列
</div>
<div class="queue-stats">
<span>总请求: {{ totalRequests }}</span>
<span>待处理: {{ pendingRequests.length }}</span>
@@ -127,32 +175,57 @@
>
<span class="req-id">#{{ req.id }}</span>
<span class="req-arrow"></span>
<span v-if="req.assignedServer" class="req-target" :style="{ color: req.serverColor }">
<span
v-if="req.assignedServer"
class="req-target"
:style="{ color: req.serverColor }"
>
{{ req.assignedServer }}
</span>
<span v-else class="req-status">{{ req.statusText }}</span>
<span
v-else
class="req-status"
>{{ req.statusText }}</span>
</div>
</div>
</div>
<div class="strategy-stats">
<div class="stats-title">📊 负载分布统计</div>
<div class="stats-title">
📊 负载分布统计
</div>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value">{{ avgLoad }}%</div>
<div class="stat-label">平均负载</div>
<div class="stat-value">
{{ avgLoad }}%
</div>
<div class="stat-label">
平均负载
</div>
</div>
<div class="stat-card">
<div class="stat-value">{{ maxLoad }}%</div>
<div class="stat-label">最高负载</div>
<div class="stat-value">
{{ maxLoad }}%
</div>
<div class="stat-label">
最高负载
</div>
</div>
<div class="stat-card">
<div class="stat-value">{{ loadStdDev }}</div>
<div class="stat-label">负载标准差</div>
<div class="stat-value">
{{ loadStdDev }}
</div>
<div class="stat-label">
负载标准差
</div>
</div>
<div class="stat-card">
<div class="stat-value">{{ mostBusyServer || '-' }}</div>
<div class="stat-label">最忙服务器</div>
<div class="stat-value">
{{ mostBusyServer || '-' }}
</div>
<div class="stat-label">
最忙服务器
</div>
</div>
</div>
</div>
@@ -5,67 +5,119 @@
<template>
<div class="nginx-architecture-demo">
<div class="header">
<div class="title"> Nginx 架构揭秘为什么它能扛住百万并发</div>
<div class="subtitle">Master-Worker 进程模型 + 事件驱动 = 高性能的秘诀</div>
<div class="title">
Nginx 架构揭秘为什么它能扛住百万并发
</div>
<div class="subtitle">
Master-Worker 进程模型 + 事件驱动 = 高性能的秘诀
</div>
</div>
<div class="architecture-diagram">
<div class="diagram-title">Nginx 进程架构图</div>
<div class="diagram-title">
Nginx 进程架构图
</div>
<div class="process-layer master-layer">
<div class="process master">
<div class="process-icon">👑</div>
<div class="process-icon">
👑
</div>
<div class="process-info">
<div class="process-name">Master 进程</div>
<div class="process-desc">管理所有 Worker负责配置加载平滑升级</div>
<div class="process-name">
Master 进程
</div>
<div class="process-desc">
管理所有 Worker负责配置加载平滑升级
</div>
</div>
</div>
</div>
<div class="connections">
<div class="connection-line" v-for="n in workerCount" :key="n"></div>
<div
v-for="n in workerCount"
:key="n"
class="connection-line"
/>
</div>
<div class="process-layer worker-layer">
<div class="worker-controls">
<button class="control-btn" @click="decreaseWorker" :disabled="workerCount <= 1">-</button>
<button
class="control-btn"
:disabled="workerCount <= 1"
@click="decreaseWorker"
>
-
</button>
<span class="worker-count">{{ workerCount }} Worker</span>
<button class="control-btn" @click="increaseWorker" :disabled="workerCount >= 8">+</button>
<button
class="control-btn"
:disabled="workerCount >= 8"
@click="increaseWorker"
>
+
</button>
</div>
<div class="workers">
<div
class="process worker"
v-for="n in workerCount"
:key="n"
class="process worker"
:class="{ active: activeWorker === n, processing: processingWorkers.includes(n) }"
@click="activateWorker(n)"
>
<div class="process-icon"></div>
<div class="process-info">
<div class="process-name">Worker {{ n }}</div>
<div class="process-desc">处理 {{ requestCounts[n] || 0 }} 请求</div>
<div class="process-icon">
</div>
<div class="status-indicator"></div>
<div class="process-info">
<div class="process-name">
Worker {{ n }}
</div>
<div class="process-desc">
处理 {{ requestCounts[n] || 0 }} 请求
</div>
</div>
<div class="status-indicator" />
</div>
</div>
</div>
<div class="epoll-layer">
<div class="epoll-box">
<div class="epoll-title">📡 epoll (Linux) / kqueue (macOS)</div>
<div class="epoll-desc">事件驱动一个 Worker 同时处理数万个连接</div>
<div class="epoll-title">
📡 epoll (Linux) / kqueue (macOS)
</div>
<div class="epoll-desc">
事件驱动一个 Worker 同时处理数万个连接
</div>
<div class="epoll-comparison">
<div class="compare-item old">
<div class="compare-title">传统 Apache</div>
<div class="compare-detail">一个连接 = 一个进程/线程</div>
<div class="compare-result"> C10K 问题</div>
<div class="compare-title">
传统 Apache
</div>
<div class="compare-detail">
一个连接 = 一个进程/线程
</div>
<div class="compare-result">
C10K 问题
</div>
</div>
<div class="vs">
VS
</div>
<div class="vs">VS</div>
<div class="compare-item new">
<div class="compare-title">Nginx</div>
<div class="compare-detail">事件驱动 + 异步非阻塞</div>
<div class="compare-result"> 百万并发</div>
<div class="compare-title">
Nginx
</div>
<div class="compare-detail">
事件驱动 + 异步非阻塞
</div>
<div class="compare-result">
百万并发
</div>
</div>
</div>
</div>
@@ -73,31 +125,59 @@
</div>
<div class="simulation-panel">
<div class="panel-title">🎮 模拟请求处理</div>
<div class="panel-title">
🎮 模拟请求处理
</div>
<div class="sim-controls">
<button class="sim-btn" @click="simulateRequests" :disabled="isSimulating">
<button
class="sim-btn"
:disabled="isSimulating"
@click="simulateRequests"
>
{{ isSimulating ? '处理中...' : '发送 20 个并发请求' }}
</button>
<button class="sim-btn secondary" @click="resetSimulation">重置</button>
<button
class="sim-btn secondary"
@click="resetSimulation"
>
重置
</button>
</div>
<div class="sim-stats" v-if="totalRequests > 0">
<div
v-if="totalRequests > 0"
class="sim-stats"
>
<div class="stat-item">
<div class="stat-value">{{ totalRequests }}</div>
<div class="stat-label">总请求数</div>
<div class="stat-value">
{{ totalRequests }}
</div>
<div class="stat-label">
总请求数
</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ mostActiveWorker }}</div>
<div class="stat-label">最忙 Worker</div>
<div class="stat-value">
{{ mostActiveWorker }}
</div>
<div class="stat-label">
最忙 Worker
</div>
</div>
<div class="stat-item">
<div class="stat-value">{{ avgRequests.toFixed(1) }}</div>
<div class="stat-label">平均/Worker</div>
<div class="stat-value">
{{ avgRequests.toFixed(1) }}
</div>
<div class="stat-label">
平均/Worker
</div>
</div>
</div>
</div>
<div class="config-tip">
<div class="tip-title">💡 生产环境建议</div>
<div class="tip-title">
💡 生产环境建议
</div>
<div class="tip-content">
<strong>Worker 数量 = CPU 核心数</strong>通常设置为 auto Nginx 自动检测
<br>
@@ -5,12 +5,18 @@
<template>
<div class="rate-limiting-demo">
<div class="header">
<div class="title"> 限流算法系统不会被"流量洪水"冲垮的秘诀</div>
<div class="subtitle">想象成水坝的闸门控制水流速度防止下游被淹没</div>
<div class="title">
限流算法系统不会被"流量洪水"冲垮的秘诀
</div>
<div class="subtitle">
想象成水坝的闸门控制水流速度防止下游被淹没
</div>
</div>
<div class="algorithm-selector">
<div class="selector-title">选择限流算法</div>
<div class="selector-title">
选择限流算法
</div>
<div class="algorithm-tabs">
<button
v-for="algo in algorithms"
@@ -26,44 +32,70 @@
<div class="visualization-area">
<div class="vis-header">
<div class="vis-title">{{ currentAlgoData.visualTitle }}</div>
<div class="vis-title">
{{ currentAlgoData.visualTitle }}
</div>
<div class="vis-controls">
<button class="control-btn" @click="toggleSimulation" :disabled="isSimulating">
<button
class="control-btn"
:disabled="isSimulating"
@click="toggleSimulation"
>
{{ isSimulating ? '模拟中...' : '▶ 开始模拟' }}
</button>
<button class="control-btn reset" @click="resetSimulation"> 重置</button>
<button
class="control-btn reset"
@click="resetSimulation"
>
重置
</button>
</div>
</div>
<!-- 令牌桶可视化 -->
<div v-if="currentAlgo === 'token'" class="token-bucket-vis">
<div
v-if="currentAlgo === 'token'"
class="token-bucket-vis"
>
<div class="bucket-container">
<div class="bucket">
<div class="bucket-label">令牌桶</div>
<div class="bucket-label">
令牌桶
</div>
<div class="tokens-area">
<div
v-for="n in bucketState.tokens"
:key="n"
class="token"
:style="{ animationDelay: `${n * 0.1}s` }"
>🪙</div>
>
🪙
</div>
</div>
<div class="bucket-capacity">
{{ bucketState.tokens }} / {{ bucketState.capacity }} 令牌
</div>
<div class="bucket-capacity">{{ bucketState.tokens }} / {{ bucketState.capacity }} 令牌</div>
</div>
<div class="token-producer">
<div class="producer-label"> 令牌产生器 ({{ bucketState.rate }}/)</div>
<div class="producer-label">
令牌产生器 ({{ bucketState.rate }}/)
</div>
<div class="producer-stream">
<div
v-for="n in 3"
:key="n"
class="producing-token"
:style="{ animationDelay: `${n * 0.3}s` }"
>🪙</div>
>
🪙
</div>
</div>
</div>
</div>
<div class="requests-queue">
<div class="queue-title">📥 请求队列</div>
<div class="queue-title">
📥 请求队列
</div>
<div class="requests">
<div
v-for="(req, index) in requestQueue"
@@ -80,46 +112,65 @@
</div>
<!-- 漏桶可视化 -->
<div v-if="currentAlgo === 'leaky'" class="leaky-bucket-vis">
<div
v-if="currentAlgo === 'leaky'"
class="leaky-bucket-vis"
>
<div class="leaky-container">
<div class="leaky-bucket">
<div class="bucket-label">漏桶</div>
<div class="bucket-label">
漏桶
</div>
<div class="bucket-content">
<div
class="water-level"
:style="{ height: `${(leakyState.current / leakyState.capacity) * 100}%` }"
></div>
/>
</div>
<div class="bucket-stats">
{{ leakyState.current }} / {{ leakyState.capacity }} 请求
</div>
<div class="bucket-stats">{{ leakyState.current }} / {{ leakyState.capacity }} 请求</div>
</div>
<div class="leak-hole">
<div class="hole">🔘</div>
<div class="leak-rate"> 流出速率: {{ leakyState.rate }}/</div>
<div class="hole">
🔘
</div>
<div class="leak-rate">
流出速率: {{ leakyState.rate }}/
</div>
</div>
</div>
<div class="leaky-legend">
<div class="legend-item">
<span class="legend-color water"></span>
<span class="legend-color water" />
<span>桶内请求排队中</span>
</div>
<div class="legend-item">
<span class="legend-color hole"></span>
<span class="legend-color hole" />
<span>匀速流出处理中</span>
</div>
<div class="legend-item">
<span class="legend-color overflow"></span>
<span class="legend-color overflow" />
<span>桶满溢出被拒绝</span>
</div>
</div>
</div>
<!-- 滑动窗口可视化 -->
<div v-if="currentAlgo === 'sliding'" class="sliding-window-vis">
<div
v-if="currentAlgo === 'sliding'"
class="sliding-window-vis"
>
<div class="window-container">
<div class="window-label"> 时间窗口过去1分钟</div>
<div class="window-label">
时间窗口过去1分钟
</div>
<div class="window-timeline">
<div class="time-marks">
<span v-for="n in 6" :key="n">{{ 60 - (n - 1) * 10 }}s</span>
<span
v-for="n in 6"
:key="n"
>{{ 60 - (n - 1) * 10 }}s</span>
</div>
<div class="window-bars">
<div
@@ -129,7 +180,10 @@
:class="{ active: slot.count > 0, current: index === slidingWindow.currentSlot }"
:style="{ height: `${Math.min((slot.count / 20) * 100, 100)}%` }"
>
<span class="slot-count" v-if="slot.count > 0">{{ slot.count }}</span>
<span
v-if="slot.count > 0"
class="slot-count"
>{{ slot.count }}</span>
</div>
</div>
</div>
@@ -144,7 +198,10 @@
</div>
<div class="stat">
<span class="stat-label">剩余额度:</span>
<span class="stat-value" :class="{ warning: slidingWindow.remaining < 20 }">{{ slidingWindow.remaining }}</span>
<span
class="stat-value"
:class="{ warning: slidingWindow.remaining < 20 }"
>{{ slidingWindow.remaining }}</span>
</div>
</div>
</div>
@@ -152,7 +209,9 @@
</div>
<div class="comparison-section">
<div class="section-title">📊 三种算法对比</div>
<div class="section-title">
📊 三种算法对比
</div>
<table class="comparison-table">
<thead>
<tr>
@@ -164,31 +223,41 @@
</thead>
<tbody>
<tr>
<td class="dim">核心思想</td>
<td class="dim">
核心思想
</td>
<td>桶里装令牌有令牌才能通过</td>
<td>请求进桶匀速流出处理</td>
<td>统计时间窗口内的请求数</td>
</tr>
<tr>
<td class="dim">突发流量</td>
<td class="dim">
突发流量
</td>
<td> 允许一定程度的突发桶里有令牌</td>
<td> 强制平滑突发会被缓存或拒绝</td>
<td> 严格按窗口计数超出一律拒绝</td>
</tr>
<tr>
<td class="dim">适用场景</td>
<td class="dim">
适用场景
</td>
<td>API 限流带宽控制允许突发</td>
<td>需要严格匀速处理的场景如消息队列</td>
<td>精确统计"1分钟内最多100次"</td>
</tr>
<tr>
<td class="dim">实现复杂度</td>
<td class="dim">
实现复杂度
</td>
<td>中等</td>
<td>中等</td>
<td>较高需要记录每个时间窗口的请求</td>
</tr>
<tr>
<td class="dim">Nginx 配置</td>
<td class="dim">
Nginx 配置
</td>
<td>limit_req_zone (漏桶)</td>
<td>limit_req_zone (漏桶)</td>
<td>需第三方模块或 Lua</td>
@@ -198,7 +267,9 @@
</div>
<div class="nginx-config">
<div class="config-title">📝 Nginx 限流配置示例</div>
<div class="config-title">
📝 Nginx 限流配置示例
</div>
<div class="config-tabs">
<button
v-for="config in nginxConfigs"
@@ -211,9 +282,16 @@
</div>
<pre class="config-code"><code>{{ currentNginxConfig.code }}</code></pre>
<div class="config-explanation">
<div class="exp-title">💡 配置说明</div>
<div class="exp-title">
💡 配置说明
</div>
<ul>
<li v-for="(item, index) in currentNginxConfig.explanation" :key="index">{{ item }}</li>
<li
v-for="(item, index) in currentNginxConfig.explanation"
:key="index"
>
{{ item }}
</li>
</ul>
</div>
</div>
@@ -5,8 +5,12 @@
<template>
<div class="reverse-proxy-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">
@@ -25,52 +29,104 @@
</div>
<div class="flow-container">
<div class="flow-row" v-if="mode === 'forward'">
<div
v-if="mode === 'forward'"
class="flow-row"
>
<div class="flow-card client">
<div class="icon">👤</div>
<div class="label">用户 (想翻墙)</div>
<div class="icon">
👤
</div>
<div class="label">
用户 (想翻墙)
</div>
</div>
<div class="arrow-box">
<div class="arrow"></div>
<div class="note">发给代理</div>
<div class="arrow">
</div>
<div class="note">
发给代理
</div>
</div>
<div class="flow-card proxy forward">
<div class="icon">🔓</div>
<div class="label">正向代理 (VPN/SS)</div>
<div class="tag">代理客户端</div>
<div class="icon">
🔓
</div>
<div class="label">
正向代理 (VPN/SS)
</div>
<div class="tag">
代理客户端
</div>
</div>
<div class="arrow-box">
<div class="arrow"></div>
<div class="note">转发请求</div>
<div class="arrow">
</div>
<div class="note">
转发请求
</div>
</div>
<div class="flow-card target">
<div class="icon">🌐</div>
<div class="label">目标网站 (Google)</div>
<div class="icon">
🌐
</div>
<div class="label">
目标网站 (Google)
</div>
</div>
</div>
<div class="flow-row" v-if="mode === 'reverse'">
<div
v-if="mode === 'reverse'"
class="flow-row"
>
<div class="flow-card client">
<div class="icon">👤</div>
<div class="label">用户 (浏览器)</div>
<div class="icon">
👤
</div>
<div class="label">
用户 (浏览器)
</div>
</div>
<div class="arrow-box">
<div class="arrow"></div>
<div class="note">访问域名</div>
<div class="arrow">
</div>
<div class="note">
访问域名
</div>
</div>
<div class="flow-card proxy reverse">
<div class="icon">🛡</div>
<div class="label">反向代理 (Nginx)</div>
<div class="tag">代理服务器</div>
<div class="icon">
🛡
</div>
<div class="label">
反向代理 (Nginx)
</div>
<div class="tag">
代理服务器
</div>
</div>
<div class="arrow-box">
<div class="arrow"></div>
<div class="note">负载均衡</div>
<div class="arrow">
</div>
<div class="note">
负载均衡
</div>
</div>
<div class="flow-card server">
<div class="icon"></div>
<div class="label">后端服务器集群</div>
<div class="sub-label">Web1 | Web2 | Web3</div>
<div class="icon">
</div>
<div class="label">
后端服务器集群
</div>
<div class="sub-label">
Web1 | Web2 | Web3
</div>
</div>
</div>
</div>
@@ -81,19 +137,33 @@
{{ mode === 'forward' ? '🔓 正向代理特点' : '🛡️ 反向代理特点' }}
</div>
<ul class="detail-list">
<li v-for="(item, index) in currentFeatures" :key="index">{{ item }}</li>
<li
v-for="(item, index) in currentFeatures"
:key="index"
>
{{ item }}
</li>
</ul>
</div>
<div class="detail-card">
<div class="detail-title">💡 典型使用场景</div>
<div class="detail-title">
💡 典型使用场景
</div>
<ul class="detail-list">
<li v-for="(item, index) in currentScenarios" :key="index">{{ item }}</li>
<li
v-for="(item, index) in currentScenarios"
:key="index"
>
{{ item }}
</li>
</ul>
</div>
</div>
<div class="memory-trick">
<div class="trick-title">🧠 记忆口诀</div>
<div class="trick-title">
🧠 记忆口诀
</div>
<div class="trick-content">
<p v-if="mode === 'forward'">
<strong>"正向代理 = 代理客户端"</strong> 客户端知情服务器只知道代理IP
@@ -5,56 +5,86 @@
<template>
<div class="routing-rules-demo">
<div class="header">
<div class="title">🧭 路由规则如何把请求送到正确的服务</div>
<div class="subtitle">想象成快递分拣中心根据地址把包裹分配到不同的配送站</div>
<div class="title">
🧭 路由规则如何把请求送到正确的服务
</div>
<div class="subtitle">
想象成快递分拣中心根据地址把包裹分配到不同的配送站
</div>
</div>
<div class="playground">
<div class="playground-header">
<div class="playground-title">🎮 路由规则实验室</div>
<div class="playground-subtitle">输入一个 URL看看它会被路由到哪个服务</div>
<div class="playground-title">
🎮 路由规则实验室
</div>
<div class="playground-subtitle">
输入一个 URL看看它会被路由到哪个服务
</div>
</div>
<div class="input-section">
<div class="input-group">
<label>HTTP 方法</label>
<select v-model="request.method">
<option value="GET">GET</option>
<option value="POST">POST</option>
<option value="PUT">PUT</option>
<option value="DELETE">DELETE</option>
<option value="GET">
GET
</option>
<option value="POST">
POST
</option>
<option value="PUT">
PUT
</option>
<option value="DELETE">
DELETE
</option>
</select>
</div>
<div class="input-group flex-2">
<label>URL 路径</label>
<input
type="text"
v-model="request.path"
type="text"
placeholder="/api/users/123"
@keyup.enter="matchRoute"
/>
>
</div>
<div class="input-group">
<label>Header (可选)</label>
<input
type="text"
v-model="request.header"
type="text"
placeholder="X-Version: v2"
/>
>
</div>
</div>
<button class="match-btn" @click="matchRoute" :disabled="isMatching">
<button
class="match-btn"
:disabled="isMatching"
@click="matchRoute"
>
{{ isMatching ? '匹配中...' : '🔍 开始匹配' }}
</button>
<div class="result-section" v-if="matchResult">
<div
v-if="matchResult"
class="result-section"
>
<div :class="['result-card', matchResult.found ? 'success' : 'fail']">
<div class="result-header">
<div class="result-icon">{{ matchResult.found ? '✅' : '❌' }}</div>
<div class="result-title">{{ matchResult.found ? '匹配成功' : '未找到匹配规则' }}</div>
<div class="result-icon">
{{ matchResult.found ? '' : '' }}
</div>
<div class="result-title">
{{ matchResult.found ? '匹配成功' : '未找到匹配规则' }}
</div>
</div>
<div class="result-detail" v-if="matchResult.found">
<div
v-if="matchResult.found"
class="result-detail"
>
<div class="detail-row">
<span class="label">目标服务</span>
<span class="value service">{{ matchResult.service }}</span>
@@ -72,7 +102,10 @@
<span class="value url">{{ matchResult.targetUrl }}</span>
</div>
</div>
<div class="result-suggestion" v-else>
<div
v-else
class="result-suggestion"
>
<p>💡 建议检查</p>
<ul>
<li>路径是否以 /api 开头</li>
@@ -85,7 +118,9 @@
</div>
<div class="rules-table">
<div class="table-title">📋 当前路由规则表</div>
<div class="table-title">
📋 当前路由规则表
</div>
<table>
<thead>
<tr>
@@ -96,19 +131,29 @@
</tr>
</thead>
<tbody>
<tr v-for="(rule, index) in routingRules" :key="index"
:class="{ active: matchResult && matchResult.ruleIndex === index }">
<tr
v-for="(rule, index) in routingRules"
:key="index"
:class="{ active: matchResult && matchResult.ruleIndex === index }"
>
<td>{{ index + 1 }}</td>
<td><code>{{ rule.match }}</code></td>
<td><span class="service-tag">{{ rule.service }}</span></td>
<td><code v-if="rule.rewrite">{{ rule.rewrite }}</code><span v-else class="no-rewrite"></span></td>
<td>
<code v-if="rule.rewrite">{{ rule.rewrite }}</code><span
v-else
class="no-rewrite"
></span>
</td>
</tr>
</tbody>
</table>
</div>
<div class="quick-presets">
<div class="presets-title">🚀 快速测试示例</div>
<div class="presets-title">
🚀 快速测试示例
</div>
<div class="preset-buttons">
<button
v-for="preset in presets"
@@ -5,69 +5,111 @@
<template>
<div class="ssl-termination-demo">
<div class="header">
<div class="title">🔒 SSL 终结HTTPS 流量的"解密官"</div>
<div class="subtitle">想象成公司的前台接待对外使用正式头衔HTTPS对内用内部称呼HTTP负责"翻译"身份</div>
<div class="title">
🔒 SSL 终结HTTPS 流量的"解密官"
</div>
<div class="subtitle">
想象成公司的前台接待对外使用正式头衔HTTPS对内用内部称呼HTTP负责"翻译"身份
</div>
</div>
<div class="ssl-flow">
<div class="flow-title">🔐 HTTPS 流量解密流程</div>
<div class="flow-title">
🔐 HTTPS 流量解密流程
</div>
<div class="flow-diagram">
<!-- 客户端 -->
<div class="flow-node client">
<div class="node-icon">👤</div>
<div class="node-label">客户端 (浏览器)</div>
<div class="node-detail">发起 HTTPS 请求</div>
<div class="node-icon">
👤
</div>
<div class="node-label">
客户端 (浏览器)
</div>
<div class="node-detail">
发起 HTTPS 请求
</div>
</div>
<div class="flow-arrow encrypted">
<div class="arrow-line"></div>
<div class="arrow-line" />
<div class="arrow-label">
<span class="lock-icon">🔒</span>
<span>TLS 加密连接</span>
</div>
<div class="cert-info">
<div class="cert-item"><span class="cert-label">证书:</span> *.example.com</div>
<div class="cert-item"><span class="cert-label">算法:</span> TLS 1.3</div>
<div class="cert-item"><span class="cert-label">加密:</span> AES-256-GCM</div>
<div class="cert-item">
<span class="cert-label">证书:</span> *.example.com
</div>
<div class="cert-item">
<span class="cert-label">算法:</span> TLS 1.3
</div>
<div class="cert-item">
<span class="cert-label">加密:</span> AES-256-GCM
</div>
</div>
</div>
<!-- Nginx -->
<div class="flow-node nginx">
<div class="node-icon">🚪</div>
<div class="node-label">Nginx (SSL 终结)</div>
<div class="node-icon">
🚪
</div>
<div class="node-label">
Nginx (SSL 终结)
</div>
<div class="node-actions">
<div class="action"><span class="action-icon">📜</span> 校验证书</div>
<div class="action"><span class="action-icon">🔓</span> 解密流量</div>
<div class="action"><span class="action-icon">📝</span> 添加 X-Forwarded-*</div>
<div class="action">
<span class="action-icon">📜</span> 校验证书
</div>
<div class="action">
<span class="action-icon">🔓</span> 解密流量
</div>
<div class="action">
<span class="action-icon">📝</span> 添加 X-Forwarded-*
</div>
</div>
</div>
<div class="flow-arrow plain">
<div class="arrow-line"></div>
<div class="arrow-line" />
<div class="arrow-label">
<span class="unlock-icon">🔓</span>
<span>HTTP 明文</span>
</div>
<div class="headers-info">
<div class="header-item">X-Forwarded-For: 203.0.113.42</div>
<div class="header-item">X-Forwarded-Proto: https</div>
<div class="header-item">X-Real-IP: 203.0.113.42</div>
<div class="header-item">
X-Forwarded-For: 203.0.113.42
</div>
<div class="header-item">
X-Forwarded-Proto: https
</div>
<div class="header-item">
X-Real-IP: 203.0.113.42
</div>
</div>
</div>
<!-- 后端服务 -->
<div class="flow-node backend">
<div class="node-icon"></div>
<div class="node-label">后端服务集群</div>
<div class="node-detail">专注于业务逻辑无需处理 TLS</div>
<div class="node-icon">
</div>
<div class="node-label">
后端服务集群
</div>
<div class="node-detail">
专注于业务逻辑无需处理 TLS
</div>
</div>
</div>
</div>
<div class="cert-management">
<div class="section-title">📜 SSL 证书管理</div>
<div class="section-title">
📜 SSL 证书管理
</div>
<div class="cert-tabs">
<button
@@ -82,14 +124,30 @@
<div class="cert-content">
<!-- 证书申请流程 -->
<div v-if="currentCertTab === 'apply'" class="apply-flow">
<div
v-if="currentCertTab === 'apply'"
class="apply-flow"
>
<div class="flow-steps">
<div v-for="(step, index) in certSteps" :key="index" class="cert-step">
<div class="step-badge">{{ index + 1 }}</div>
<div
v-for="(step, index) in certSteps"
:key="index"
class="cert-step"
>
<div class="step-badge">
{{ index + 1 }}
</div>
<div class="step-content">
<div class="step-title">{{ step.title }}</div>
<div class="step-desc">{{ step.desc }}</div>
<div class="step-command" v-if="step.command">
<div class="step-title">
{{ step.title }}
</div>
<div class="step-desc">
{{ step.desc }}
</div>
<div
v-if="step.command"
class="step-command"
>
<code>{{ step.command }}</code>
</div>
</div>
@@ -98,7 +156,10 @@
</div>
<!-- Nginx 配置 -->
<div v-if="currentCertTab === 'config'" class="nginx-config">
<div
v-if="currentCertTab === 'config'"
class="nginx-config"
>
<pre class="config-block"><code>server {
listen 443 ssl http2;
server_name api.example.com;
@@ -147,15 +208,27 @@ server {
</div>
<!-- 最佳实践 -->
<div v-if="currentCertTab === 'bestpractice'" class="best-practices">
<div
v-if="currentCertTab === 'bestpractice'"
class="best-practices"
>
<div class="practices-grid">
<div v-for="practice in bestPractices" :key="practice.id" class="practice-card">
<div
v-for="practice in bestPractices"
:key="practice.id"
class="practice-card"
>
<div class="practice-header">
<span class="practice-icon">{{ practice.icon }}</span>
<span class="practice-title">{{ practice.title }}</span>
</div>
<div class="practice-content">{{ practice.content }}</div>
<div class="practice-code" v-if="practice.code">
<div class="practice-content">
{{ practice.content }}
</div>
<div
v-if="practice.code"
class="practice-code"
>
<code>{{ practice.code }}</code>
</div>
</div>
@@ -165,31 +238,57 @@ server {
</div>
<div class="benefits-section">
<div class="section-title"> SSL 终结的核心优势</div>
<div class="section-title">
SSL 终结的核心优势
</div>
<div class="benefits-grid">
<div class="benefit-card">
<div class="benefit-icon">🚀</div>
<div class="benefit-title">性能提升</div>
<div class="benefit-desc">TLS 握手和加密解密是 CPU 密集型操作集中在 Nginx 处理后端服务专注业务逻辑整体吞吐量提升 2-5 </div>
<div class="benefit-icon">
🚀
</div>
<div class="benefit-title">
性能提升
</div>
<div class="benefit-desc">
TLS 握手和加密解密是 CPU 密集型操作集中在 Nginx 处理后端服务专注业务逻辑整体吞吐量提升 2-5
</div>
</div>
<div class="benefit-card">
<div class="benefit-icon">🔧</div>
<div class="benefit-title">简化运维</div>
<div class="benefit-desc">证书统一管理只需在 Nginx 配置一次无需在每个后端服务重复配置证书续期更换一键完成</div>
<div class="benefit-icon">
🔧
</div>
<div class="benefit-title">
简化运维
</div>
<div class="benefit-desc">
证书统一管理只需在 Nginx 配置一次无需在每个后端服务重复配置证书续期更换一键完成
</div>
</div>
<div class="benefit-card">
<div class="benefit-icon">🛡</div>
<div class="benefit-title">集中安全</div>
<div class="benefit-desc">SSL/TLS 配置统一管控强制使用最新协议版本和密码套件统一添加安全响应头HSTSCSP </div>
<div class="benefit-icon">
🛡
</div>
<div class="benefit-title">
集中安全
</div>
<div class="benefit-desc">
SSL/TLS 配置统一管控强制使用最新协议版本和密码套件统一添加安全响应头HSTSCSP
</div>
</div>
<div class="benefit-card">
<div class="benefit-icon">📊</div>
<div class="benefit-title">统一监控</div>
<div class="benefit-desc">所有 HTTPS 流量经过 Nginx可以统一记录访问日志分析 SSL 握手性能监控证书有效期便于审计和排障</div>
<div class="benefit-icon">
📊
</div>
<div class="benefit-title">
统一监控
</div>
<div class="benefit-desc">
所有 HTTPS 流量经过 Nginx可以统一记录访问日志分析 SSL 握手性能监控证书有效期便于审计和排障
</div>
</div>
</div>
</div>