
1) 【一句话结论】
针对数千学生实时竞赛系统,核心方案是采用WebSocket实现低延迟双向通信,Nginx通过least_conn算法负载均衡分发连接至C++事件驱动服务器集群,服务器利用libevent+线程池分离I/O与业务逻辑,通过Redis Pub/Sub持久化广播结果,结合请求ID幂等性保障数据一致性,支撑高并发实时交互。
2) 【原理/概念讲解】
老师口吻:首先解释WebSocket。传统HTTP是短连接,像打电话要反复拨号,WebSocket是长连接,握手后持续通信,像电话线一直连着,实时双向。Nginx作为反向代理,配置upstream的least_conn,根据后端服务器当前连接数动态分配请求,避免热点服务器资源耗尽。C++服务器用libevent的epoll事件驱动模型,监听文件描述符事件,快速响应每个连接的读写,避免阻塞。Redis Pub/Sub的持久化配置,比如设置max-redis-pubsub-persistence为1,并使用XREAD命令结合事务,确保消息不丢失。客户端重连机制:心跳检测(如每3秒发送ping),断线后自动重连,同步本地状态(如未提交的题目),服务器端维护连接池,重连后同步用户状态。
3) 【对比与适用场景】
| 对比项 | WebSocket | HTTP长轮询 |
|---|---|---|
| 定义 | 基于TCP的长连接,支持客户端主动推送 | 客户端保持HTTP连接,服务器定期推送 |
| 特性 | 双向实时、低延迟、连接保持 | 每次请求需建立连接,延迟高 |
| 使用场景 | 实时交互(直播竞赛、在线答题) | 早期实时应用(如聊天室,但性能差) |
| 注意点 | 需服务器支持,握手复杂 | 实现简单,但高并发下性能瓶颈明显 |
4) 【示例】
客户端(JavaScript):
const ws = new WebSocket('wss://compete.xueqiu.com');
ws.onopen = () => console.log('连接成功');
ws.onmessage = (msg) => {
const data = JSON.parse(msg.data);
if (data.type === 'result') {
console.log('得分:', data.score, '正确:', data.correct);
}
};
ws.send(JSON.stringify({ questionId: 1, answer: 'A', requestId: '12345' }));
服务器(C++,libevent+线程池):
// 伪代码
struct Connection {
int fd;
std::string requestId;
std::thread* worker;
};
void onConnect(struct event* ev, short events, void* arg) {
Connection* conn = (Connection*)arg;
// 启动工作线程处理业务
conn->worker = new std::thread([conn]() {
while (true) {
std::string msg;
// 读取消息
if (read(conn->fd, &msg) <= 0) break;
// 解析请求ID,检查是否已处理
if (isProcessed(conn->requestId)) continue;
// 处理答案
bool correct = checkAnswer(qid, answer);
int score = correct ? 10 : 0;
json result = { {"type", "result"}, {"questionId", qid}, {"correct", correct}, {"score", score} };
// 广播
redisPubSub.publish("competition", result.dump());
// 标记为已处理
markProcessed(conn->requestId);
}
});
}
int main() {
struct event_base* base = event_base_new();
struct event* ev = event_new(base, 8080, EV_READ | EV_PERSIST, onConnect, nullptr);
event_set(ev, 8080, 0);
event_add(ev, nullptr);
event_base_dispatch(base);
return 0;
}
5) 【面试口播版答案】
面试官您好,针对数千学生同时参与直播竞赛的实时系统,我的核心方案是采用WebSocket实现低延迟双向通信。具体来说,Nginx作为反向代理,通过upstream的least_conn算法将WebSocket连接请求动态分发到后端C++服务器集群,服务器利用libevent事件驱动模型结合线程池,将I/O操作与业务逻辑分离,高效处理高并发连接。学生提交答案后,服务器通过Redis Pub/Sub持久化广播结果,同时利用请求ID的幂等性确保每个学生的答案只处理一次,避免重复得分。比如客户端建立WebSocket连接后,发送答案,服务器立即判断正确性并返回得分,所有学生都能实时看到结果,保证竞赛的公平性和实时性。
6) 【追问清单】
7) 【常见坑/雷区】