会议平台后端优化方案

news2024/12/26 14:02:48

会议平台后端优化方案

通过RTC的学习,我了解到了端对端技术,就想着做一个节省服务器资源的会议平台
之前做了这个项目,快手二面被问到卡着不知如何介绍,便有了这篇文章

分析当下机制

相对于传统视频平台(SFU,MCU架构)

之前帮学长做压测RTC监控时,10M校园网宽带,标清画质只能跑到22个(MCU架构),

毕竟是监控就只能卡在自己宽带下了

image-20241001001901382

所有资源从服务器拉取,大量的上下传极大的加重了服务器压力,

目前行业内如直播方式更多是使用分布式服务器,

如我在北京开了直播,一部分观众在广东一部分在上海,

此时,视频流将先传到北京服务器转发到广东服务器和上海服务器进行一个服务器的分压处理,当然下面还有更多子服务器去分压,

而这种形式对于我们这种学生开发者是行不通的,我们只能省吃俭用租用一台公有云,

而在之前开发 ESP32 Mesh 组网时来了灵感

ESP-MESH - ESP32 - — ESP-IDF 编程指南 v4.3.1 文档 (espressif.com)

image-20241001002741260

我们如果做一个多人群聊(类似会议平台),只需要使用每个设备进行 P2P 的 RTC 推拉流可以完美减缓服务器压力,

而服务器只需要负责信令汇总交换,还有客户端检测,保活的操作即可

甚至我的轻量级服务器也能跑上(压测时,用到了redis缓冲mysql)

也许好的想法总是相似的,网上看到了很多大佬也这样去做了(MESH架构)

image-20241001003423135

我第一次尝试使用了 golang gin 去写一个信令交互(也是有golang直接能调库使用RTC的原因),

实现的并不是很理想,

做了票据凭证登录(邮箱),

设计了 Mysql数据库(大家平时多练习,面试要手撕),

最后实现了点对点,并不是很理想。

毕竟跑在一个2核1G内存的超级轻量级服务器上的,

配合其他项目。。。。单是跑起来就直接爆了几次内存,(也不太敢和别人聊这个项目最后成果)

更别提对他进行压测,

后来重新捡起来后,打算直接融入到我的博客网站其中一个路由中,

实现了一个保障会议成员隐私,使用完无痕,的会议平台。(仅供学习参考)

image-20241001013250207

会议创建机制

一个post创建会议

会议号类似秘钥,名字可填可不填,不填我爬 ip 用 ip代指,

房间创建后永久保留唯一留痕在这里(不是说无痕吗?创建的人还是要跟踪记录爬取一下的哈哈哈,之前经历了sql注入,还好做了防注入 )

a20f0822cbcb1e32db5ec3580c9d65e

爬取ip以及地点 看是谁创的

image-20241001005056686

image-20241001005121677

这里meeting_id作为索引,指向另一张表参加此id的人群,

来完成一个快速查表工作,

当然此时还没加入会议,

加入会议机制

对于保活,和及时提出会议,像我个人感受

我每次开完会更希望直接关闭浏览器实现一个全自动退出会议的方式,

image-20241001012330563

关闭浏览器后,检测断开直接删除

image-20241001012344316

我之前开发 esp32 AP 模式时(哈哈哈还是esp)

需要通过wifi节点的web直接对esp进行操作,如小车前进后退

使用了websocket,

我便考虑了websocket,他可以实时检测,又是全双工,

完美的事物总是有缺陷的一面,

我需要给他额外开端口,

这可不是什么好方式,又要去申请一张证书,不然万一来个中间人攻击那大家的隐私不是没了吗?

此时我发现了SocketIO 基于websocket,可跑在443端口的神器,

python示例代码:

首先,便是相应库使用,以及对基础连接进行反应

from flask import Flask
from flask_socketio import SocketIO, emit,session

app = Flask(__name__)
socketio = SocketIO(app)

@socketio.on('connect')
def handle_connect():
    print('A client has connected.')

接下来我们就要处理加入事件

拿到消息后,存入到session中,以便后续对断开操作

@socketio.on('join')
def handle_join(data):
    
    meeting_id = data['meeting_id']
    user_id = data['user_id']
    SDP = data['SDP']
    CANDIDATE = data['CANDIDATE']
    session['user_id'] = user_id
    session['meeting_id'] = meeting_id
    print(f"User {user_id} try to join meeting {meeting_id}")

连接数据库

把这个用户归类到相应room中

以便后续处理

connection = connector.connect(**db_config)
        cursor = connection.cursor()
        
        cursor.execute("SELECT * FROM meetings WHERE meeting_id = %s", (meeting_id,))
        meeting = cursor.fetchone()
        if not meeting:
            socketio.emit('join_response', {"error": "会议不存在"}, to=request.sid)
            return
        

        print(f'a client {user_id} has joined the meeting {meeting_id}')
        # 将用户加入房间
        join_room(meeting_id)
        # 插入参与者到数据库
        cursor.execute("INSERT INTO participants (meeting_id, user_id,SDP,CANDIDATE) VALUES (%s, %s,%s,%s)", (meeting_id, user_id,SDP,CANDIDATE))
        connection.commit()

拉取room的所有人进行广播,更新参与者,把拉取的数据整理成字典,传至前端

#返回此会议室的所有人的信令
        cursor.execute("SELECT user_id, SDP, CANDIDATE FROM participants WHERE meeting_id = %s",(meeting_id,))
        room_participants = cursor.fetchall()
        dist={}
        for i in room_participants:
            dist[i[0]]={"SDP":i[1],"CANDIDATE":i[2]}
        
        # 成功后发送确认消息
        socketio.emit('join_response', {"status": "success", "message": f"User {user_id} joined meeting {meeting_id}.","room_participants":dist}, to=request.sid)


    # 通知所有房间内的客户端更新参与者列表
    socketio.emit('update_participants', participants_list[meeting_id], room=meeting_id)

image-20241001012453533

{
	王宇:{
		Can:“ssss”,
		Sdp:“sss”
	},
	王:{
		Can:“ssss”,
		Sdp:“sss”
	},。。。。。
}

检测断联,从session读取操作对象信息

@socketio.on('disconnect')
def handle_disconnect():
    
    user_id = session.get('user_id')
    meeting_id = session.get('meeting_id')
    print(f'A client {user_id} has disconnected.')
    leave_room(meeting_id)

        # 从数据库中删除参与者
           connection = connector.connect(**db_config)
           cursor = connection.cursor()
            
           cursor.execute("DELETE FROM participants WHERE meeting_id = %s AND user_id = %s", (meeting_id, user_id))
           connection.commit()


        # 通知所有客户端更新参与者列表
        socketio.emit('update_participants', participants_list[meeting_id], room=meeting_id)


通过以上能简单完成我们想要的效果.

测试并进行二次开发

我先对上面板块进行单元测试

发现没有任何问题,

将其与博客网站进行整体测试,

最终没有问题直接上传代码更新了服务器(2c 1g 30MB),

我们对其进行压测,

在无连接时,内存占用到了700mb

哈哈哈至少还有250mb给我们用

(我这里把 ip 限制关闭和 uwsgi 限制客户端个数关闭了 ,本来只能一个ip五个坑位,这里放开以便测试)

通过python自动构建了客户端与其连接,

当产生到320+客户端的时候,成功崩了

但通过查询内存占用的时候(如下图)

发现还不到20Mb,零头都没到啊,看来不是内存原因

image-20241001014730406

30/8大概在3.8mb/s

大概问题出现在宽带,

但相对传统架构(MCU)真的节省太多昂贵的服务器资源了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2181693.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

windows 驱动实例分析系列-定时日志的COM驱动

本文章的前置文章为: windows 驱动编写原则 windows COM驱动 案例 windows COM驱动的I/O处理 在前面的设计中,主要是对windows提供的VirtualSerial源代码的讲解,但是那个驱动其实是一个空壳驱动,用于学习的,在I/O处理中,也讲述了serial I/O处理的本质,接下来会将这些…

PGMP-03战略一致性

1.概要 program strategy alignment:战略一致性 2.详细

css的背景background属性

CSS的background属性是一个简写属性,它允许你同时设置元素的多个背景相关的子属性。使用这个属性可以简化代码,使其更加清晰和易于维护。background属性可以设置不同的子属性。 background子属性 定义背景颜色 使用background-color属性 格式&#x…

经典文献阅读之--WiROS(用于机器人的WiFi感知工具箱)

0. 简介 近期的许多研究探索了使用基于WiFi的感知技术来改善SLAM(同时定位与地图构建)、机器人操控或探索。此外,WiFi的广泛可用性使其成为最具优势的射频信号。但WiFi传感器缺乏一个准确、易处理、多功能的工具箱,这限制了它们与…

MicoZone-Maven

一、理论 Maven 是 Apache 软件基金会组织维护的一款专门为 Java 项目提供项目构建和依赖管理支持的工具。 通过Maven管理依赖的优势: 1、通过在pom.xml中指定jar包坐标即可自动从仓库下载依赖 2、如果jar包存在子依赖会自动下载子依赖包 3、如果jar包之间存在冲突…

Web安全 - 服务端请求伪造SSRF(Server-Side Request Forgery)

文章目录 OWASP 2023 TOP 10SSRF 导图SSRF 概念SSRF的工作原理SSRF攻击场景SSRF防御策略1. 严格验证用户输入2. 禁用或限制对内部网络的访问3. 强制使用外部API代理4. 禁止直接访问敏感资源5. 输入内容长度限制6. 检测和监控7. 确保对HTTP请求的处理安全 SSRF防御实现方案1. 白…

【鸿蒙开发】05 登录Demo解析

文章目录 一、功能介绍 在鸿蒙开发中,一个完善的登录功能是许多应用程序的基础需求。本文将详细介绍一个鸿蒙 App 登录 Demo,包括其功能介绍、代码解析以及代码 demo 的下载地址。 本文初始代码从华为开发者网站下载,根据该Demo进行内容调整。…

【Fast-LIO系列】Fast-LIO、Fast-LIO2、Faster-LIO系列特点分析

【FAST-LIO】Fast-LIO系列特点分析 1. FAST-LIO核心贡献1.将IMU和Lidar特征点紧耦合在一起2.使用反向传播考虑到了运动补偿3. 基于IESKF中的 卡尔曼增益更新 K 2. FAST-LIO2核心贡献(2021年)1. 不用线,面特征点而使用全局点云2. 使用ikd-tree存储点云3. ikd-Tree 3.…

P3131 [USACO16JAN] Subsequences Summing to Sevens S Python题解

[USACO16JAN] Subsequences Summing to Sevens S 题目描述 Farmer John’s N N N cows are standing in a row, as they have a tendency to do from time to time. Each cow is labeled with a distinct integer ID number so FJ can tell them apart. FJ would like to ta…

C语言 | Leetcode C语言题解之第448题找到所有数组中消失的数字

题目&#xff1a; 题解&#xff1a; int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize) {for (int i 0; i < numsSize; i) {int x (nums[i] - 1) % numsSize;nums[x] numsSize;}int* ret malloc(sizeof(int) * numsSize);*returnSize 0;for (in…

特征工程——一门提高机器学习性能的艺术

当前围绕人工智能(AI)和机器学习(ML)展开的许多讨论以模型为中心&#xff0c;聚焦于 ML和深度学习(DL)的最新进展。这种模型优先的方法往往对用于训练这些模型的数据关注不足&#xff0c;甚至完全忽视。类似MLOps的领域正迅速发展&#xff0c;通过系统性地训练和利用ML模型&…

ZYNQ: GPIO 之 MIO 控制 LED 实验

GPIO 之 MIO 控制 LED 实验目的 使用 GPIO 通过两个 MIO 引脚控制 PS 端两个 LED 的亮灭&#xff0c;实现底板上 PS_LED0、PS_LED1 两个 LED 灯同亮同灭的效果。 简介 ZYNQ PS 中的外设&#xff08;如 USB 控制器、UART 控制器、I2C 控制器以及 GPIO 等等&#xff09;可以通…

亲测无限坐席在线客服系统源码/二开版/基于ThinkPHP+搭建教程

源码简介&#xff1a; 亲测了一款实用的无限坐席在线客服系统源码&#xff0c;这可是基于ThinkPHP框架开发的二开版哦&#xff01;里面还附带了一份超详细的搭建教程。 安装过程简直不能更简单&#xff0c;只需一键操作&#xff0c;启动两个端口就搞定了。而且&#xff0c;它…

动态库的加载全过程

区分一组概念&#xff1a;逻辑地址&#xff0c;虚拟地址&#xff0c;物理地址。 逻辑地址&#xff1a;是我们的代码在编译过程&#xff0c;编译器帮对每一条代码所生成的指令所编写的地址。 物理地址&#xff1a;当程序被放入到内存中时&#xff0c;内存与每一条指令所对应的…

回执单识别-银行回单识别API-文字识别OCR API

银行回单是一种由银行提供的交易凭证&#xff0c;记录了账户资金的交易明细。它通常包括存款、取款、转账、汇款、支付等各种类型的资金往来信息。银行回单可以是纸质的&#xff0c;也可以是电子版的&#xff0c;内容详尽记录了交易的相关信息&#xff0c;具有法律效力&#xf…

CSS 效果:实现动态展示双箭头

最近写了一段 CSS 样式&#xff0c;虽然不难&#xff0c;但实现过程比较繁琐。这个效果结合了两个箭头&#xff0c;一个突出&#xff0c;一个内缩&#xff0c;非常适合用于步骤导航或选项卡切换等场景。样式不仅仅是静态的&#xff0c;还可以通过点击 click 或者 hover 事件&am…

【机器学习(五)】分类和回归任务-AdaBoost算法

文章目录 一、算法概念一、算法原理&#xff08;一&#xff09;分类算法基本思路1、训练集和权重初始化2、弱分类器的加权误差3、弱分类器的权重4、Adaboost 分类损失函数5、样本权重更新6、AdaBoost 的强分类器 &#xff08;二&#xff09;回归算法基本思路1、最大误差的计算2…

JavaSE——面向对象2:方法的调用机制、传参机制、方法递归、方法重载、可变参数、作用域

目录 一、成员方法 (一)方法的快速入门 (二)方法的调用机制(重要) (三)方法的定义 (四)注意事项和使用细节 1.访问修饰符(作用是控制方法的使用范围) 2.返回的数据类型 3.方法名 4.形参列表 5.方法体 6.方法调用细节说明 (五)传参机制 1.基本数据类型的传参机制 …

C++模拟实现vector容器【万字模拟✨】

更多精彩内容..... &#x1f389;❤️播主の主页✨&#x1f618; Stark、-CSDN博客 本文所在专栏&#xff1a; 学习专栏C语言_Stark、的博客-CSDN博客 项目实战C系列_Stark、的博客-CSDN博客 数据结构与算法_Stark、的博客-CSDN博客 座右铭&#xff1a;梦想是一盏明灯&#xff…

idea2023-快速搭建一个本地tomcat的javaWeb项目(从0到1保姆教学)

前言 如何在新版idea中搭建一个javaWeb项目&#xff0c;并且应用在物理的tomcat中&#xff0c;本文将进行从零到一&#xff0c;完成搭建步骤&#xff0c;以及相关注意事项的讲解。 为什么需要配置tomcat&#xff1f; 我们开发的javaWeb项目&#xff0c;最后都需要打包部署到真正…