WebSocket 实战案例:从设计到部署

在前六篇文章中,我们深入探讨了 WebSocket 的基础原理、服务端开发、客户端实现、安全实践、性能优化和测试调试。今天,让我们通过一个实战案例,看看如何将这些知识应用到实际项目中。我曾在一个大型在线教育平台中,通过 WebSocket 实现了实时互动课堂,支持了数万名师生的同时在线。

项目背景

我们要实现一个实时互动课堂系统,主要功能包括:

  1. 实时音视频
  2. 课堂互动
  3. 共享白板
  4. 实时聊天
  5. 课堂管理

让我们从系统设计开始。

系统架构

实现系统架构:

// app.js
const express = require('express')
const https = require('https')
const fs = require('fs')
const path = require('path')
const WebSocket = require('ws')
const Redis = require('ioredis')
const { ClusterManager } = require('./cluster-manager')
const { ConnectionPool } = require('./connection-pool')
const { MessageQueue } = require('./message-queue')
const { RoomManager } = require('./room-manager')
const { UserManager } = require('./user-manager')
const { MediaServer } = require('./media-server')

class ClassroomServer {
  constructor(options = {}) {
    this.options = {
      port: 8080,
      sslPort: 8443,
      redisUrl: 'redis://localhost:6379',
      mediaServer: 'localhost:8000',
      ...options
    }

    // 初始化组件
    this.cluster = new ClusterManager()
    this.pool = new ConnectionPool()
    this.queue = new MessageQueue()
    this.rooms = new RoomManager()
    this.users = new UserManager()
    this.media = new MediaServer(this.options.mediaServer)

    this.initialize()
  }

  // 初始化服务器
  async initialize() {
    // 创建 Express 应用
    this.app = express()
    this.setupExpress()

    // 创建 HTTPS 服务器
    this.server = https.createServer({
      key: fs.readFileSync('server.key'),
      cert: fs.readFileSync('server.cert')
    }, this.app)

    // 创建 WebSocket 服务器
    this.wss = new WebSocket.Server({
      server: this.server,
      path: '/ws'
    })

    // 连接 Redis
    this.redis = new Redis(this.options.redisUrl)

    // 设置事件处理器
    this.setupEventHandlers()

    // 启动服务器
    await this.start()
  }

  // 设置 Express
  setupExpress() {
    // 静态文件
    this.app.use(express.static('public'))

    // API 路���
    this.app.use('/api', require('./routes/api'))

    // 错误处理
    this.app.use((err, req, res, next) => {
      console.error('Express error:', err)
      res.status(500).json({ error: 'Internal server error' })
    })
  }

  // 设置事件处理器
  setupEventHandlers() {
    // WebSocket 连接
    this.wss.on('connection', (ws, req) => {
      this.handleConnection(ws, req)
    })

    // Redis 订阅
    this.redis.on('message', (channel, message) => {
      this.handleRedisMessage(channel, message)
    })

    // 进程消息
    process.on('message', (message) => {
      this.handleProcessMessage(message)
    })
  }

  // 处理 WebSocket 连接
  async handleConnection(ws, req) {
    try {
      // 验证用户
      const user = await this.users.authenticate(req)

      // 创建连接
      const connection = this.pool.createConnection(ws, user)

      // 加入房间
      const roomId = req.query.roomId
      if (roomId) {
        await this.rooms.joinRoom(roomId, connection)
      }

      // 设置消息处理器
      ws.on('message', (message) => {
        this.handleMessage(connection, message)
      })

      // 设置关闭处理器
      ws.on('close', () => {
        this.handleClose(connection)
      })

      // 发送欢迎消息
      connection.send({
        type: 'welcome',
        data: {
          user: user.toJSON(),
          room: roomId ? await this.rooms.getRoomInfo(roomId) : null
        }
      })
    } catch (error) {
      console.error('Connection error:', error)
      ws.close()
    }
  }

  // 处理消息
  async handleMessage(connection, message) {
    try {
      const data = JSON.parse(message)

      // 验证消息
      if (!this.validateMessage(data)) {
        throw new Error('Invalid message format')
      }

      // 处理不同类型的消息
      switch (data.type) {
        case 'chat':
          await this.handleChatMessage(connection, data)
          break
        case 'whiteboard':
          await this.handleWhiteboardMessage(connection, data)
          break
        case '
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值