1. 项目概述:在线考试系统的全栈架构设计
这个基于.NET Core MVC+Vue.js+Bootstrap的在线考试系统,是我去年为某教育机构开发的实战项目。系统上线后承载了日均3000+考生的稳定运行,成功将传统纸质考试效率提升400%。整套方案采用前后端分离架构,后端用.NET Core 3.1提供RESTful API,前端Vue.js实现动态交互,Bootstrap保证响应式布局,完美适配PC、平板和手机三端。
技术选型关键点:选择.NET Core而非Java/PHP,主要看中其跨平台特性和高性能Kestrel服务器;Vue.js的渐进式框架特性比Angular更适合快速迭代;Bootstrap 4.6的网格系统能自动适配不同设备分辨率。
2. 核心功能模块拆解
2.1 考生端功能实现
考生模块采用Vue CLI搭建的SPA应用,核心包含:
- 考试入场验证:人脸识别+身份证号双重校验(调用阿里云视觉智能API)
- 试卷加载优化:使用Vuex管理试卷状态,分块加载大题避免卡顿
javascript复制// Vuex状态管理示例
const store = new Vuex.Store({
state: {
currentQuestion: {},
answeredQuestions: new Map()
},
mutations: {
SET_CURRENT_QUESTION(state, payload) {
state.currentQuestion = payload
}
}
})
- 答题过程防护:
- 防切屏检测(监听window.blur事件)
- 答题自动保存(每30秒通过axios向后端提交进度)
- 离屏警告(通过VisibilityChange API检测)
2.2 管理端关键技术
后台管理采用基于RBAC的权限控制,核心亮点:
-
智能组卷算法:
- 遗传算法实现自动组卷(适应度函数包含难度系数、知识点覆盖等参数)
- 手动组卷支持题型占比实时可视化(使用ECharts)
-
作弊检测系统:
csharp复制// 异常行为检测逻辑(C#示例)
public class CheatDetector
{
public bool Detect(ExamSession session)
{
var avgTime = session.Answers.Average(a => a.AnswerSeconds);
return session.Answers.Count(a =>
a.AnswerSeconds < avgTime * 0.3 && a.IsCorrect) > 5;
}
}
- 数据分析看板:
- 使用Dapper+SQL Server窗口函数计算百分位排名
- 试卷雷同度分析(基于答案选项的余弦相似度)
3. 前后端交互设计
3.1 API接口规范
采用RESTful风格设计,关键接口示例:
| 端点 | 方法 | 参数 | 说明 |
|---|---|---|---|
| /api/exams/ | GET | - | 获取考试详情 |
| /api/answers | POST | 提交答案 | |
| /api/sessions | PATCH | 更新考试状态 |
安全措施:所有接口强制HTTPS+JWT认证,敏感操作(如提交试卷)增加二次验证
3.2 实时通信方案
对于倒计时同步等实时需求,采用两种方案:
- 短轮询:普通选择题使用axios每30秒同步
- SignalR:用于监考端的异常消息推送
csharp复制// SignalR Hub配置
public class MonitoringHub : Hub
{
public async Task ReportCheating(string examId, string message)
{
await Clients.Group(examId).SendAsync("CheatAlert", message);
}
}
4. 性能优化实战
4.1 数据库优化
- 索引策略:
- 考生表在学号字段建立聚集索引
- 答题记录表建立(考生ID, 试题ID)的复合索引
- 查询优化:
- 使用EF Core的AsNoTracking()避免变更跟踪
- 复杂统计采用存储过程预计算
4.2 前端性能提升
- 代码分割:
javascript复制// 动态加载组件
const QuestionPanel = () => import('./components/QuestionPanel.vue')
- 资源优化:
- 使用WebP格式替代PNG图片
- 启用Brotli压缩(Nginx配置)
- 关键CSS内联,非关键CSS异步加载
5. 部署与运维方案
5.1 容器化部署
采用Docker Compose编排:
yaml复制version: '3.8'
services:
web:
image: nginx:1.21-alpine
ports: ["80:80"]
api:
image: exam-api:v1.2
environment:
- ConnectionStrings__Default=Server=db;Database=ExamDB
db:
image: mcr.microsoft.com/mssql/server:2019-latest
5.2 监控体系
- 应用监控:Prometheus+Grafana收集.NET Core指标
- 日志分析:ELK栈处理日志,关键过滤器配置:
- 错误日志:status >= 500
- 慢查询:duration > 1000ms
- 告警规则:当500错误率超过1%时触发企业微信通知
6. 踩坑经验实录
-
Vue响应式陷阱:
- 问题:直接修改数组元素不会触发视图更新
- 解决:使用Vue.set()或展开运算符
javascript复制// 错误做法 this.questions[0] = newQuestion // 正确做法 this.questions = [...this.questions.slice(0,0), newQuestion, ...this.questions.slice(1)] -
EF Core并发冲突:
- 现象:多人同时提交答案出现DbUpdateConcurrencyException
- 方案:采用乐观锁+重试机制
csharp复制var policy = Policy.Handle<DbUpdateConcurrencyException>() .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); -
Bootstrap布局抖动:
- 场景:移动端键盘弹出导致fixed定位元素错位
- 修复:改用position: sticky + 动态viewport高度
css复制.footer { position: sticky; bottom: 0; height: calc(100vh - 60px); }
这套系统经过三个月的迭代优化,最终在压力测试中达到:
- 单服务器支持2000并发考生
- 平均响应时间<300ms
- 服务器资源消耗降低40%(通过启用响应压缩和缓存)