1. 项目背景与核心价值
在大学校园周边,美食资源丰富但信息分散,学生群体普遍面临"今天吃什么"的决策难题。传统的美食推荐方式存在三个痛点:信息更新滞后、个人口味匹配度低、缺乏社交互动属性。这个基于Spring Boot的校园美食探索平台,正是为了解决这些实际问题而生。
我去年参与开发了某高校的类似系统,上线三个月内用户自发贡献了1200+条真实评价,证明了这类平台的用户需求确实存在。与商业化的美食APP不同,我们的平台有三个独特优势:第一,完全聚焦校园周边3公里范围内的餐饮场景;第二,用户都是同学关系链,评价可信度更高;第三,整合了课表数据实现"下课吃什么"的智能推荐。
2. 技术架构设计解析
2.1 整体技术栈选型
后端采用Spring Boot 2.7 + MyBatis Plus组合,这个选择经过了多重考量。相比纯Spring MVC,Spring Boot的自动配置特性让我们的开发效率提升了40%左右。数据库使用MySQL 8.0,主要考虑到事务处理能力和对地理空间数据的支持。
前端采用Vue 3 + Element Plus,这个组合在管理后台开发中特别高效。但有个坑需要注意:Element Plus的按需引入配置要特别小心,我们在初期打包体积达到了8MB,优化后降到1.2MB。
2.2 核心功能模块设计
系统划分为五个核心模块:
- 用户服务:处理注册登录、个人资料
- 内容服务:管理餐厅信息和点评
- 推荐服务:基于协同过滤的个性化推荐
- 社交服务:关注、私信、动态
- 地图服务:周边餐厅的地理位置展示
其中推荐服务的设计最有挑战性。我们最终采用混合推荐策略:
- 基于内容的推荐(60%权重):分析用户历史点评关键词
- 协同过滤推荐(30%权重):相似口味用户的偏好
- 热门推荐(10%权重):近期校园热点餐厅
3. 关键实现细节剖析
3.1 餐厅数据采集方案
初期我们尝试了三种数据获取方式:
- 手动录入:准确但效率低
- 网络爬虫:有法律风险
- 用户众包:最终选择方案
开发了一个"餐厅猎人"激励计划,用户上传新餐厅信息通过审核后,可获得平台虚拟勋章。这个设计使我们在首月就收集了200+家餐厅数据。
3.2 地理位置服务集成
使用高德地图API实现周边搜索功能时,要注意两个关键参数:
java复制// 搜索半径设置为3000米(校园周边)
params.put("radius", "3000");
// 排序方式为距离优先
params.put("sortrule", "distance");
实测发现,不加距离排序时,API返回结果可能与用户实际位置偏差很大。另外记得申请企业级API密钥,个人开发者账号有每日调用限额。
3.3 点评防刷机制
为了防止恶意刷好评,我们实现了三级防御:
- 基础规则:同一IP每小时限3条点评
- 行为分析:检测点评时间分布异常
- 人工审核:敏感词触发人工复核
这套机制上线后,垃圾点评减少了87%。核心代码如下:
java复制public boolean checkReviewValid(Review review) {
// IP频率检查
if(ipService.checkOverLimit(review.getIp())) {
return false;
}
// 敏感词检测
if(sensitiveWordFilter.contains(review.getContent())) {
review.setStatus(REVIEW_STATUS_PENDING);
return true;
}
// 行为分析
return behaviorAnalyzer.analyze(review);
}
4. 推荐算法优化实践
4.1 冷启动解决方案
新用户没有历史数据时,我们采用三级降级策略:
- 首先尝试基于院系推荐(文理科口味差异)
- 其次使用同年级热门餐厅
- 最后展示全站精选
这个方案使新用户的首屏点击率提升了35%。
4.2 实时反馈机制
当用户对推荐结果点击"不喜欢"时,系统会立即调整推荐权重。我们设计了一个动态衰减因子:
code复制新权重 = 原权重 * (1 - 衰减系数)^n
其中n是连续不喜欢的次数,衰减系数设为0.5。这个简单的调整让推荐准确率提高了22%。
5. 性能优化关键点
5.1 缓存策略设计
采用Redis三级缓存架构:
- 热点数据:永久缓存(如学校基本信息)
- 常规数据:24小时TTL(如餐厅基础信息)
- 动态数据:5分钟TTL(如实时点评数)
特别注意缓存击穿问题,我们的解决方案是:
java复制public Restaurant getRestaurant(Long id) {
// 尝试从缓存获取
Restaurant restaurant = redisTemplate.opsForValue().get("restaurant:" + id);
if (restaurant == null) {
// 获取分布式锁
if (lock.tryLock()) {
try {
// 双重检查
restaurant = redisTemplate.opsForValue().get("restaurant:" + id);
if (restaurant == null) {
// 数据库查询
restaurant = restaurantMapper.selectById(id);
// 写入缓存,设置随机过期时间防止雪崩
redisTemplate.opsForValue().set(
"restaurant:" + id,
restaurant,
30 + (int)(Math.random() * 20),
TimeUnit.MINUTES
);
}
} finally {
lock.unlock();
}
} else {
// 未获取到锁时,返回旧数据或默认值
restaurant = getDefaultRestaurant();
}
}
return restaurant;
}
5.2 数据库优化经验
MySQL方面我们做了三个重要优化:
- 餐厅表添加空间索引:
ALTER TABLE restaurants ADD SPATIAL INDEX(position) - 点评表采用分库分表:按餐厅ID哈希分片
- 建立复合索引:
(user_id, create_time)组合索引使个人主页查询速度提升10倍
6. 部署与运维实践
6.1 容器化部署方案
使用Docker Compose编排服务,关键配置如下:
yaml复制version: '3'
services:
app:
image: foodie-platform:${TAG}
deploy:
resources:
limits:
cpus: '2'
memory: 2G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
redis:
image: redis:6-alpine
command: redis-server --save 60 1 --loglevel warning
volumes:
- redis_data:/data
volumes:
redis_data:
特别注意Java应用的JVM参数配置:
code复制-XX:+UseG1GC -Xmx1500m -XX:MaxRAMPercentage=75.0
6.2 监控系统搭建
采用Prometheus + Grafana监控体系,重点监控三个指标:
- 接口响应时间P99 < 500ms
- 推荐服务成功率 > 99.5%
- MySQL活跃连接数 < 50
我们设置的关键告警规则示例:
yaml复制- alert: HighErrorRate
expr: rate(http_server_requests_errors_total[1m]) > 0.1
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate on {{ $labels.instance }}"
description: "Error rate is {{ $value }}"
7. 典型问题排查实录
7.1 推荐结果不稳定问题
现象:同一用户连续刷新,推荐结果差异很大
排查过程:
- 检查日志发现推荐服务响应时间波动大
- 追踪到数据库查询时快时慢
- 最终定位到MySQL没有使用索引
解决方案:
sql复制ALTER TABLE user_behavior ADD INDEX idx_uid_ct (user_id, create_time);
7.2 内存泄漏问题定位
现象:容器每隔12小时左右就会被OOMKill
排查工具:
- jmap生成堆转储文件
- MAT分析工具定位问题
发现:未关闭的WebClient实例累积
修复方案:
java复制@Bean
public WebClient webClient() {
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(
HttpClient.create().connectionProvider(
ConnectionProvider.builder("custom")
.maxConnections(50)
.pendingAcquireTimeout(Duration.ofSeconds(10))
.build()
)
))
.build();
}
8. 项目演进方向
目前我们正在开发三个新功能:
- 外卖档口实时排队人数预测
- 食堂人流量热力图
- 美食短视频分享功能
其中人流量预测采用了LSTM神经网络,训练数据来自:
- 历史人流量统计
- 课程表数据
- 天气信息
- 特殊事件日历
初期测试显示,预测准确率能达到75%左右,还在持续优化中。