# OfferFlow
**Repository Path**: SapientialM/OfferFlow
## Basic Information
- **Project Name**: OfferFlow
- **Description**: OfferFlow 是一个面向校招求职的项目,覆盖高并发即时通讯与 AI 模拟面试两大场景。
- **Primary Language**: HTML
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-03-21
- **Last Updated**: 2026-05-13
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# OfferFlow - 校招求职助手平台
**OfferFlow** 是一个面向校招求职者的综合服务平台,覆盖**高并发即时通讯**与 **AI 模拟面试**两大场景。
[](https://openjdk.org/)
[](https://openjdk.org/)
[](https://spring.io/projects/spring-boot)
[](https://netty.io/)
[](https://react.dev/)
[](https://www.postgresql.org/)
[](./LICENSE)
---
## 🎯 项目亮点
### OfferFlow-Chat(高并发即时通讯)
- **5,000 并发好友消息零丢包**:k6 压测 36 万+ 消息,到达率 **100%**,P95 延迟 **284ms**
- **Netty WebSocket 网关**:主从线程池模型,单实例支撑数万长连接,配合 PooledByteBufAllocator 降低 GC 压力
- **自研一致性哈希负载均衡**:160 虚拟节点实现连接精准路由,节点增减时最小化数据迁移
- **Redis Lua 原子红包系统**:原子扣减 + 重复领取校验 + 24h 自动过期退款,杜绝超卖
- **Kafka 双通道架构**:生产者 → Kafka → 消费者 → 数据库,配合消息幂等、顺序保证、3 次重试 + 死信队列,保障 99.9% 消息可靠投递
### OfferFlow-Interview(AI 面试助手)
- **RAG 检索增强生成**:Spring AI + pgvector 构建知识引擎,向量相似度检索耗时 **< 500ms**
- **多格式文档解析**:Apache Tika 支持 PDF/DOCX/TXT,内容哈希自动去重,解析准确率 **92%**
- **Redis Stream 异步流水线**:简历分析、知识库向量化异步解耦,处理效率提升 **300%**,内置失败自动重试(最多 3 次)
- **多维度令牌桶限流**:Redisson + Lua 实现用户级 + 接口级双维度限流,防止 API 滥用
- **AI 模拟面试**:基于简历内容智能生成针对性题目,支持多轮追问与分批评估,规避大模型 Token 溢出
---
## 🏗️ 系统架构
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ OfferFlow Platform │
├─────────────────────────────┬───────────────────────────────────────────────┤
│ OfferFlow-Chat │ OfferFlow-Interview │
│ (高并发即时通讯) │ (AI 面试助手) │
├─────────────────────────────┼───────────────────────────────────────────────┤
│ • Netty WebSocket 网关 │ • Spring AI + 通义千问大模型 │
│ • 一致性哈希负载均衡 │ • PostgreSQL + pgvector 向量检索 │
│ • Kafka 双通道消息队列 │ • Redis Stream 异步任务处理 │
│ • Redis Lua 原子操作 │ • 多维度令牌桶限流 │
│ • Nacos 服务发现 │ • Apache Tika 多格式文档解析 │
│ • MySQL 主从 │ • iText 8 PDF 报告导出 │
└─────────────────────────────┴───────────────────────────────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 统一前端 (React + TypeScript) │
│ ┌──────────────┬──────────────────────────────┐ │
│ │ IM 界面 │ 面试与知识库界面 │ │
│ └──────────────┴──────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
```
---
## 📦 模块说明
| 模块 | 技术栈 | 说明 |
|------|--------|------|
| [offerflow-chat](./offerflow-chat/) | Java 17, Spring Boot 2.6, Netty 4.1, Kafka, Redis, Nacos, MySQL | 高并发即时通讯网关与业务服务(7 微服务) |
| [offerflow-interview](./offerflow-interview/) | Java 21, Spring Boot 4.0, Spring AI 2.0, PostgreSQL/pgvector, Redis | AI 面试助手 / RAG 知识引擎 |
| [offerflow-frontend](./offerflow-frontend/) | React 18, TypeScript, Tailwind CSS | 统一前端(IM + Interview) |
---
## 🔧 核心技术实现
### 1. Netty WebSocket 高并发网关
```java
// 线程池优化配置
boss-threads = 1
worker-threads = Math.min(4, CPU * 2) // 容器环境下限制最大 4 个
io-ratio = 70% // 70% 时间用于 IO
// JVM 容器化优化
-XX:+UseContainerSupport
-XX:MaxRAMPercentage=75%
-Xss256k
-XX:+UseG1GC
-XX:+UseStringDeduplication
```
- **主从线程池**:Boss 线程负责连接接入,Worker 线程负责 IO 读写,避免线程资源浪费
- **内存池**:PooledByteBufAllocator 减少堆外内存分配与 GC 压力
- **心跳保活**:24h 长连接自动保活与断线重连
### 2. 一致性哈希负载均衡
```java
public class ConsistentHash {
private TreeMap nodes = new TreeMap<>();
private static final int VIRTUAL_NODES = 160; // 虚拟节点数
private int getHash(String str) {
// FNV1_32_HASH 算法
final int p = 16777619;
int hash = (int) 2166136261L;
for (int i = 0; i < str.length(); i++) {
hash = (hash ^ str.charAt(i)) * p;
hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5;
}
return Math.abs(hash);
}
}
```
- **160 虚拟节点**:负载分布更均匀
- **TreeMap 查找**:O(log n) 时间复杂度
- **动态扩缩容**:节点增减仅影响相邻区间,最小化连接迁移
### 3. Redis Lua 原子红包系统
```lua
local redPacketKey = KEYS[1]
local userReceivedKey = KEYS[2]
local userId = ARGV[1]
-- 重复领取校验
if redis.call('SISMEMBER', userReceivedKey, userId) == 1 then
return -1
end
-- 原子扣减
local remaining = redis.call('DECR', redPacketKey)
if remaining < 0 then
redis.call('INCR', redPacketKey)
return -2
end
redis.call('SADD', userReceivedKey, userId)
return remaining
```
- **原子性**:Lua 脚本在 Redis 单线程执行,天然避免竞态条件
- **超卖防护**:扣减后回滚机制,确保红包数量不会为负
- **过期退款**:Redis Key 24h 自动过期,触发退款流程
### 4. Kafka 消息可靠投递
```
生产者 → Kafka → 消费者 → 数据库
↓ ↑
└──── 实时推送 ─────┘
```
- **幂等消费**:消息 ID 去重,防止重复处理
- **顺序保证**:同一会话消息按顺序投递
- **失败重试**:3 次重试后进入死信队列,人工介入
- **手动确认**:消费者 ACK 后才提交 Offset,确保消息不丢失
### 5. RAG 检索增强生成
```
文档上传 → 文本分块 → 向量化 → 向量存储 → 相似度检索 → Prompt 增强 → LLM 生成
```
- **智能分块**:约 500 tokens/块,重叠 50 tokens,保留上下文连续性
- **分批向量化**:每批最多 10 条,避免 Embedding API 限流
- **余弦相似度检索**:pgvector `vector_cosine_ops` + IVFFlat 索引,Top-K 检索耗时 < 500ms
### 6. 多维度智能限流
```java
@RateLimit(key = "user:#{userId}", permitsPerSecond = 5, capacity = 10)
@RateLimit(key = "api:interview", permitsPerSecond = 100, capacity = 200)
public InterviewAnswer submitAnswer(Long userId, String answer) { ... }
```
- **用户级限流**:防止单用户滥用
- **接口级限流**:保护全局 AI API 调用配额
- **Redis Lua 令牌桶**:分布式一致性,支持突发流量平滑处理
---
## 🚀 性能优化成果
### JVM 与容器镜像优化
| 优化项 | 原配置 | 新配置 | 效果 |
|--------|--------|--------|------|
| 基础镜像 | eclipse-temurin:8-jdk-alpine | eclipse-temurin:8-jre-alpine | 镜像大小 **-66%** |
| JVM 堆内存 | 默认 | `-XX:MaxRAMPercentage=75%` | 容器感知,防止 OOM |
| 线程栈 | 512k | 256k | 每个线程省 256k |
| GC 算法 | 默认 | G1GC + 字符串去重 | 停顿时间 < 50ms |
| Metaspace | 无限制 | 64m ~ 128m | 限制元空间泄漏 |
### 连接池优化
- **HikariCP**:读多写少服务 `max=10/min-idle=2`;写频繁服务 `max=15/min-idle=3`
- **Redisson**:连接池从 500 削减至 20,线程数从 4 降至 2,切换 Kryo5Codec 节省 30%+ 内存
- **Kafka 消费者**:批量拉取 500 条/次,并发度 2,开启批处理监听
### 容器资源规划(4C8G 单节点)
| 组件 | CPU | 内存 |
|------|-----|------|
| 业务服务(合并后 4 个) | 3.5C | 3.5G |
| 基础设施(MySQL/Redis/Kafka) | 2C | 2.3G |
| **总计** | **~4C** | **~6G** |
---
## 🚀 快速开始
### 环境要求
| 依赖 | 版本 | 模块 | 必需 |
|------|------|------|------|
| JDK | 17+ | offerflow-chat | ✅ |
| JDK | 21+ | offerflow-interview | ✅ |
| Node.js | 18+ | 两者都需要 | ✅ |
| Docker | 20+ | 基础设施 | ✅ |
| Docker Compose | 2+ | 基础设施 | ✅ |
### 一键启动
```bash
# 克隆仓库
git clone https://github.com/yourusername/OfferFlow.git
cd OfferFlow
# 启动全部服务
docker-compose up -d
```
### 分别启动
**前端(统一):**
```bash
cd offerflow-frontend
pnpm install
pnpm dev
```
**IM 后端:**
```bash
cd offerflow-chat
# 1. 配置环境变量(复制 .env.example 并填写)
# 2. 启动服务
docker-compose -f docker-compose.service.yml up -d
```
**Interview 后端:**
```bash
cd offerflow-interview
cp .env.example .env
# 编辑 .env 填入 AI API Key
docker-compose up -d --build
```
### 环境变量配置
项目中的敏感信息(密码、API Key 等)均通过环境变量传入,避免硬编码。
**OfferFlow-Chat 关键变量:**
- `MYSQL_PASSWORD` — MySQL 密码
- `NACOS_PASSWORD` — Nacos 密码
- `REDIS_PASSWORD` — Redis 密码(如配置了)
- `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY` — MinIO 凭证
**OfferFlow-Interview 关键变量:**
- `AI_BAILIAN_API_KEY` — 阿里云百炼 API Key
- `POSTGRES_PASSWORD` — PostgreSQL 密码
> 💡 **获取阿里云百炼 API Key**:登录 [阿里云百炼控制台](https://bailian.console.aliyun.com/) → API Key 管理 → 创建并复制。
---
## 📊 测试报告
项目包含完整的高并发压测体系与测试报告,详见根目录 [**TEST_REPORT.md**](./TEST_REPORT.md)。
**最佳记录摘要(OfferFlow-Chat):**
- **场景**:5,000 并发用户 / 好友单聊 / k6 压测 / 60s
- **消息量**:364,965 发送 / 364,965 接收
- **到达率**:100.00% | **丢包率**:0.00% | **错误数**:0
- **延迟**:平均 52ms / P95 284ms / P99 425ms
- **性能剖析**:全链路 6 个服务 FlameGraph,精准定位 CPU 热点
---
## 📄 许可证
本项目采用 [Apache-2.0 License](./LICENSE) 开源协议。
---
**Made with ❤️ for Job Seekers**