# whushortlink **Repository Path**: mchmin/whushortlink ## Basic Information - **Project Name**: whushortlink - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-06 - **Last Updated**: 2026-06-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # whushortlink 分布式短链系统(Gitee)。后端为多模块 Maven 工程;**演示前端**为 Vite + Vue 3。 设计目标:**百万级短链的高并发跳转**(`GET /r/{shortCode}` 为热路径),生成侧负责写库、预热与安全创建。 后端细节见 [`code/backend/README.md`](code/backend/README.md),前端见 [`code/frontend-web/README.md`](code/frontend-web/README.md)。 ## 特性概览 | 能力 | 说明 | |------|------| | **跳转热路径** | Caffeine L1 → Redis Hash → 负缓存 → 限流内回源 8082 | | **Redis 结构** | `whu:sl:{code}` Hash 字段 `u/s/e/v`;`whu:sl:miss:{code}` 防穿透 | | **缓存一致性** | D2 写/删发布 `whu:sl:invalidate`,各 redirect 实例清 L1 | | **流量控制** | 全局限流、单 IP/单码 Redis 计数、8082 熔断、Nginx 网关限流(staging) | | **安全** | 创建域名策略、API Key、跳转短码校验、IP 黑名单、ingest 内网(Nginx) | | **运维** | 一键启动脚本、Docker Compose、Prometheus/Grafana(staging) | 架构与路线详见 [`docs/high-concurrency-redirect-roadmap.md`](docs/high-concurrency-redirect-roadmap.md)、[`docs/SYSTEM_ARCHITECTURE.md`](docs/SYSTEM_ARCHITECTURE.md)。 ## 仓库目录 | 路径 | 说明 | |------|------| | `code/backend/` | 四个 Spring Boot 服务(生成、跳转、统计、日志消费) | | `code/frontend-web/` | Vite + Vue 3 演示前端 | | `docker-compose.yml` | MySQL、Redis、Kafka 基础设施 | | `deploy/` | Nginx、Prometheus/Grafana、[部署说明](deploy/DEPLOYMENT.md) | | `scripts/` | 一键启动/停止(`start-dev.ps1` / `.sh` / `.bat`) | | `docs/` | 设计文档、压测说明、团队分工 | | `tests/load/` | JMeter 压测脚本与报告 | ## 环境要求 | 用途 | 依赖 | |------|------| | 后端 | JDK 8+、Maven 3.6+、MySQL 8、**Redis**(跳转缓存必需) | | 演示前端 | Node.js 18+ | | 可选 | Kafka 9092(`log-worker`;Web 演示统计可走 HTTP,不依赖 Kafka) | | 可选 | Docker(基础设施与 staging 网关/监控) | ## 快速开始 ### 一键启动(推荐) **Windows(PowerShell,仓库根目录):** ```powershell .\scripts\start-dev.ps1 ``` **Linux / macOS:** ```bash chmod +x scripts/start-dev.sh ./scripts/start-dev.sh ``` 脚本会启动 Docker(MySQL `3307`、Redis `6379`、Kafka `9092`)及四个后端 + Vite 前端(`:5173`)。 **staging 演示**(Nginx 网关 + Prometheus + Grafana + redirect 双副本): ```powershell .\scripts\start-dev.ps1 -WithStaging ``` 停止 Docker:`.\scripts\stop-dev.ps1` 或 `./scripts/stop-dev.sh`。详见 [`deploy/DEPLOYMENT.md`](deploy/DEPLOYMENT.md)。 ### 缓存预热(压测 / 跳转性能前必做) 跳转依赖 Redis 命中;创建短链后或压测前应预热: ```powershell # 全量分批预热(推荐,扫完库中有效短链) .\scripts\warmup-cache.ps1 # 仅最近 5000 条(快速) .\scripts\warmup-cache.ps1 -RecentOnly -Limit 5000 ``` 接口:`POST .../ops/cache/warmup?limit=N`(最近 N 条)或 `POST .../ops/cache/warmup-batch?batch=5000&beforeId=`(分页全量)。 ### 验证跳转 1. 浏览器打开 http://localhost:5173,生成短链并「测试跳转」。 2. 或命令行创建后访问 `http://localhost:8081/r/{shortCode}`。 ```powershell $body = '{"longUrl":"https://www.example.com/"}' Invoke-RestMethod -Uri "http://localhost:8082/api/v1/short-links" -Method Post ` -ContentType "application/json; charset=utf-8" -Body $body ``` ## 服务与端口 | 服务 | 端口 | 职责 | |------|------|------| | `redirect-service` | 8081 | **跳转热路径** `GET /r/{code}` → 302 | | `link-generator-service` | 8082 | 短链创建、查询、Redis 写/预热 | | `analytics-service` | 8083 | 访问统计 API | | `log-worker` | — | Kafka 消费(可选) | | 前端 Vite | 5173 | 演示 UI | | Nginx(staging) | 80 | 网关限流 + 多 redirect 副本 | | Grafana(staging) | 3000 | 监控大盘(admin/admin) | **手动启动**(仓库根目录): ```bash docker compose up -d mvn -f code/backend/pom.xml -pl link-generator-service spring-boot:run # 等待 Flyway 建表就绪后 mvn -f code/backend/pom.xml -pl redirect-service spring-boot:run mvn -f code/backend/pom.xml -pl analytics-service spring-boot:run ``` ## 演示前端 ```bash cd code/frontend-web && npm install && npm run dev ``` | 前端路径 | 代理目标 | |----------|----------| | `/api/v1/short-links` | `:8082` | | `/api/v1/stats` | `:8083` | | 页面 | 说明 | |------|------| | 生成短链 | 输入长链;展示 `shortUrl`(默认 `http://localhost:8081/r/...`) | | 历史记录 | 本地列表;跳转经 8081,可「演示访问」直写 ingest | | 日志分析 | PV / Top / 最近访问(约 8 秒刷新) | **日志有数据的方式**(无需 Kafka):历史页「跳转」、「演示访问」,或生成页「测试跳转」。 ## 对外接口(摘要) ### 短链生成(8082) - `POST /api/v1/short-links` — 创建;body `{ "longUrl", "ttlDays"? }` - 生产可设 `WHU_API_KEY`,请求头 `X-API-Key`;超限返回 429 - 拒绝 localhost / 内网地址;同 URL 复用未过期短链(`url_hash`) - `GET /api/v1/short-links/{shortCode}` — 查询;响应含 `longUrl`、`status`、`expireEpochSec`、`version` - `POST /api/v1/short-links/ops/cache/warmup?limit=500` — Redis Hash 预热 ### 跳转(8081,热路径) - `GET /r/{shortCode}` — 302;路径:`L1 → Redis Hash → 负缓存 → 8082` - 限流:429;8082 熔断且 cache miss:503 + `Retry-After` - Prometheus:`GET /actuator/prometheus` ### 访问统计(8083) - `GET /api/v1/stats/summary` / `rank` / `recent` - `POST /api/v1/stats/ingest` — body `{ "code" }`(生产应仅内网,见 `deploy/nginx/nginx.conf`) 完整接口见 [`docs/rest-api-specification.md`](docs/rest-api-specification.md)。 ## Redis 映射约定(D1/D2 统一) | Key | 类型 | 说明 | |-----|------|------| | `whu:sl:{code}` | HASH | `u` 长链 · `s` 状态(1/0) · `e` 过期秒(0=永久) · `v` 版本 | | `whu:sl:miss:{code}` | STRING | 负缓存,默认 TTL 60s | | `whu:sl:invalidate` | Pub/Sub | 失效广播,redirect 清 L1 | | `whu:blk:ip` | SET | IP 黑名单(`SADD whu:blk:ip `) | ## 主要配置 环境变量清单:[`deploy/env.example`](deploy/env.example)。redirect 专项说明:[`docs/redirect-service-config.md`](docs/redirect-service-config.md)。 | 变量 | 说明 | |------|------| | `SPRING_DATASOURCE_URL` | MySQL;Docker 默认端口 **3307** | | `REDIS_HOST` / `REDIS_PORT` | 跳转与生成共用 | | `WHU_CACHE_KEY_PREFIX` | 默认 `whu:sl:` | | `WHU_CACHE_MISS_PREFIX` | 默认 `whu:sl:miss:` | | `WHU_LINK_GENERATOR_BASE_URL` | redirect 回源,默认 `http://127.0.0.1:8082` | | `WHU_RL_IP_PER_MINUTE` | 单 IP 跳转限流(默认 300/min) | | `WHU_STATS_SAMPLING_RATE` | 统计采样 0.0~1.0(默认 1.0) | | `WHU_API_KEY` | 创建 API 鉴权(空则开发模式不校验) | | `SHORT_LINK_PUBLIC_BASE_URL` | 响应中 `shortUrl` 前缀,默认 `http://localhost:8081` | ## 模块协作 ``` 浏览器 → redirect:8081/r/{code} ├─ Redis Hash(主路径,预热后 >99% 命中) ├─ miss 时限流内 → link-generator:8082 └─ 异步 → analytics:8083/ingest(可采样) link-generator → MySQL + Redis 写 + 失效 Pub/Sub frontend → 8082 创建 / 8083 统计 log-worker → Kafka(可选) ``` ## 压测与文档 | 文档 | 用途 | |------|------| | [`tests/load/完整测试指南.md`](tests/load/完整测试指南.md) | 压测全流程(环境、A 创建、B 跳转、报告) | | [`tests/load/JMETER.md`](tests/load/JMETER.md) | JMeter 创建场景 GUI 详解 | | [`docs/performance-test-notes.md`](docs/performance-test-notes.md) | 压测参数 | | [`docs/team-task-allocation.md`](docs/team-task-allocation.md) | 四人分工 | | [`deploy/RELEASE-CHECKLIST.md`](deploy/RELEASE-CHECKLIST.md) | 发布与回滚 | 压测前:**先 warmup**,再对 `GET /r/{code}` 加压;对比指标见 Grafana「Redirect Overview」。 ## 编译 ```bash mvn -f code/backend/pom.xml clean package -DskipTests ``` ## 生产提示 - 设置 `WHU_API_KEY`;Nginx 对外仅暴露跳转与查询,**deny** `/api/v1/stats/ingest` - redirect 水平扩展无状态;staging 参考 `deploy/nginx/nginx.conf` 多副本 upstream - 百万链场景:批量导入 MySQL 后大 `limit` 预热,并监控 Redis 内存与 `whu.redirect.cache.*` 指标