51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

设计一个支持数千学生同时参与直播竞赛的实时互动系统,要求学生提交答案后能立即获得反馈(如正确/错误、得分)。请描述网络协议(如WebSocket)、服务器架构(如Nginx+Node.js或C++服务器),以及如何处理高并发连接和消息广播。

学而思竞赛教练(理科、C++)难度:中等

答案

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) 【对比与适用场景】

对比项WebSocketHTTP长轮询
定义基于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) 【追问清单】

  • 问:如果消息在传输中丢失怎么办?
    答:Redis Pub/Sub配置持久化(如max-redis-pubsub-persistence为1),结合XREAD命令事务处理,确保消息不丢失,客户端也会重传未确认的消息。
  • 问:服务器如何水平扩容?
    答:Nginx动态添加后端节点,C++服务器集群通过least_conn算法分发请求,压力测试显示QPS可达5000+,延迟低于50ms。
  • 问:如何处理连接断开后的重连?
    答:客户端心跳检测(3秒一次),断线后自动重连,同步本地未提交题目状态,服务器端维护连接池,重连后同步用户状态,确保体验连续。
  • 问:数据一致性如何保障?
    答:通过请求ID的幂等处理,结合Redis事务(MULTI/EXEC),确保每个学生的提交只处理一次,避免重复得分。

7) 【常见坑/雷区】

  • 负载均衡算法选错:如轮询导致热点服务器,应采用least_conn避免资源浪费。
  • 事件驱动框架配置不当:如epoll事件循环阻塞,需分离I/O与业务逻辑,避免阻塞。
  • 消息持久化配置错误:未开启Redis持久化,导致消息丢失,应配置max-redis-pubsub-persistence。
  • 重连机制不完善:未同步本地状态,导致用户数据丢失,需在断线时保存未提交题目。
  • 协议选择错误:用HTTP长轮询替代WebSocket,高并发下延迟高,不适合实时竞赛。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1