
1) 【一句话结论】
针对实时答题反馈需求,采用RESTful(HTTP短连接,JSON格式)获取初始静态数据(如题目、选项),通过WebSocket(长连接,双向实时)推送答题结果;后端结合乐观锁(防并发冲突)与消息队列(异步处理高并发任务),并设计心跳机制(2-5秒间隔,延迟阈值3秒)处理延迟与错误。
2) 【原理/概念讲解】
需明确区分RESTful与WebSocket的核心差异:
GET /questions获取题目列表),POST方法用于创建资源(非幂等,需幂等性处理,如提交答案)。混合方案中,初始数据用RESTful提高效率,实时反馈用WebSocket保证低延迟。
3) 【对比与适用场景】
| 特性 | WebSocket | RESTful |
|---|---|---|
| 定义 | 全双工通信协议(基于TCP长连接) | 基于HTTP的分布式架构风格 |
| 连接类型 | 长连接(持久化) | 短连接(请求后断开) |
| 通信方向 | 双向实时(推送/接收) | 单向(请求-响应) |
| 语义细节 | 无缓存,需处理连接断开 | GET可缓存(无副作用),POST非幂等 |
| 使用场景 | 实时数据推送(答题反馈、聊天) | 静态资源获取、批量数据查询 |
| 注意点 | 需实现心跳机制防超时 | 需处理缓存控制(如Cache-Control),POST需保证幂等性(如唯一标识或时间戳) |
4) 【示例】
// RESTful获取题目(初始数据,带缓存控制)
fetch('/api/questions?studentId=user123', {
headers: {
'Cache-Control': 'max-age=3600' // 缓存1小时
}
})
.then(res => res.json())
.then(questions => {
const socket = new WebSocket('wss://api.haofutui.com/quiz');
socket.onopen = () => {
const data = {
questionId: 1,
answer: 'A',
studentId: 'user123',
version: 1 // 乐观锁版本号
};
socket.send(JSON.stringify(data));
};
socket.onmessage = (event) => {
const result = JSON.parse(event.data);
updateUI(result);
};
socket.onerror = (error) => {
console.error('连接异常,5秒后重连');
setTimeout(() => socket.close(), 5000);
};
});
// 后端(Python伪代码,含乐观锁与消息队列)
@app.route('/api/questions/<int:qid>', methods=['GET'])
def get_question(qid):
# 缓存热点题目
if qid in hot_cache:
return jsonify(hot_cache[qid])
return jsonify(db.questions.get(qid))
@app.route('/ws/submit-answer', methods=['POST'])
def submit_answer():
data = request.get_json()
with db.transaction():
question = db.questions.get(data['questionId'])
if question.version != data['version']:
return jsonify({'error': '数据冲突'}), 409
# 异步计算得分
task_queue.put(('calculate', data))
return jsonify({'status': 'pending'})
5) 【面试口播版答案】
面试官您好,针对实时反馈答题结果的需求,我会采用RESTful+WebSocket混合架构。初始的题目、选项等静态数据通过RESTful API(JSON格式)获取,因为这类数据变化少,HTTP GET请求可缓存(比如设置Cache-Control:max-age=3600),减少后端压力;而答题后的实时结果需要WebSocket,因为它能保持长连接,实现前端主动推送(比如学生答题后,后端通过WebSocket立即返回正确/错误信息)。数据传输统一用JSON,前端发送答题数据(包含题目ID、学生ID、答案、版本号),后端处理时用乐观锁(版本号字段)防并发冲突,高并发时用消息队列(如RabbitMQ)异步计算得分,避免任务堆积。另外,设计2-5秒的心跳机制,若3秒内未收到心跳则判定连接异常,前端自动重连,确保实时性。
6) 【追问清单】
7) 【常见坑/雷区】