当前位置: 首页 > news >正文

会议平台后端优化方案

会议平台后端优化方案

通过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,sessionapp = 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_idsession['meeting_id'] = meeting_idprint(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)returnprint(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)真的节省太多昂贵的服务器资源了

相关文章:

会议平台后端优化方案

会议平台后端优化方案 通过RTC的学习,我了解到了端对端技术,就想着做一个节省服务器资源的会议平台 之前做了这个项目,快手二面被问到卡着不知如何介绍,便有了这篇文章 分析当下机制 相对于传统视频平台(SFU&#xff…...

unixODBC编程(十)分片插入长数据

遇到有LONG数据类型的表,要插入一条数据量很大的行,一次插入的缓冲区会不够大,这时需要一部分一部分的插入LONG数据,这就用到了在执行语句时动态提供数据的机制。在ODBC中要动态提供数据需要几个步骤。 1. 在绑定输入参数时&…...

【Java】—— 集合框架:Collection子接口:Set不同实现类的对比及使用(HashSet、LinkedHashSet、TreeSet)

目录 5. Collection子接口2:Set 5.1 Set接口概述 5.2 Set主要实现类:HashSet 5.2.1 HashSet概述 5.2.2 HashSet中添加元素的过程: 5.2.3 重写 hashCode() 方法的基本原则 5.2.4 重写equals()方法的基本原则 5.2.5 练习 5.3 Set实现类…...

android Activity生命周期

android 中一个 activity 在其生命周期中会经历多种状态。 您可以使用一系列回调来处理状态之间的转换。下面我们来介绍这些回调。 onCreate(创建阶段) 初始化组件:在这个阶段,Activity的主要工作是进行初始化操作。这包括为Ac…...

C#的面向对象

1)对象 算法数据结构 2)对象的行为已方法的形式定义的,属性以成员变量的形式定义的 面向对象程序设计的特点 1)封装性 2)继承性 3)多态性 知识点: 封装性面向对象的核心思想,将…...

【区别】三种命令取消已暂存的文件,处理暂存区和文件的跟踪状态

取消已暂存的文件 git restore --staged <文件>、git reset HEAD <文件> 和 git rm --cached <文件> 都可以用于取消已暂存的文件&#xff0c;但它们的作用和使用场景略有不同。下面是它们的区别&#xff1a; 1. git restore --staged <文件> 该命令…...

如何在Spring Boot中有条件地运行CommandLineRunner Bean

PS 使用 Spring Boot 3.1.2 进行测试 1.使用ConditionalOnProperty ConditionalOnProperty仅当特定属性存在或具有特定值时&#xff0c;注释才会创建 Bean 。 在此示例中&#xff0c;仅当或文件中的CommandLineRunner属性db.init.enabled设置为 true时&#xff0c;才会执行。…...

边缘自适应粒子滤波(Edge-Adaptive Particle Filter)的MATLAB函数示例,以及相应的讲解

目录 讲解 初始化 预测步骤 观测模拟 权重更新 重采样 状态估计 总结 下面是一个简单的边缘自适应粒子滤波&#xff08;&#xff09;的函数示例&#xff0c;以及相应的讲解。 程序源代码&#xff1a; function X_est edgeAdaptiveParticleFilter(numParticles, numS…...

一块1T硬盘怎么有sdb1和sdb2

在一块 1TB 硬盘上看到两个分区 sdb1 和 sdb2 是非常常见的现象。硬盘可以被划分为多个分区&#xff0c;每个分区都可以用作不同的目的&#xff0c;如存储不同类型的数据、安装不同的操作系统或为系统不同的功能提供支持。 1. 分区的概念 硬盘可以被划分为多个分区&#xff0…...

Python知识点:如何使用Flink与Python进行实时数据处理

开篇&#xff0c;先说一个好消息&#xff0c;截止到2025年1月1日前&#xff0c;翻到文末找到我&#xff0c;赠送定制版的开题报告和任务书&#xff0c;先到先得&#xff01;过期不候&#xff01; 如何使用Flink与Python进行实时数据处理 Apache Flink是一个流处理框架&#xf…...

Swagger配置且添加小锁(asp.net)(笔记)

此博客是基于 asp.net core web api(.net core3.1)框架进行操作的。 一、安装Swagger包 在 NuGet程序包管理中安装下面的两个包&#xff1a; swagger包&#xff1a;Swashbuckle.AspNetCore swagger包过滤器&#xff1a;Swashbuckle.AspNetCore.Filters 二、swagger注册 在…...

lambda表达式底层实现:反编译LambdaMetafactory + 转储dump + 运行过程 + 反汇编 + 动态指令invokedynamic

一、结论先行 lambda 底层实现机制 1.lambda 表达式的本质&#xff1a;函数式接口的匿名子类的匿名对象 2.lambda表达式是语法糖 语法糖&#xff1a;编码时是lambda简洁的表达式&#xff0c;在字节码期&#xff0c;语法糖会被转换为实际复杂的实现方式&#xff0c;含义不变&am…...

Unity初识+面板介绍

Unity版本使用 小版本号高&#xff0c;出现bug可能性更小&#xff1b;一台电脑可以安装多个版本的Unity&#xff0c;但是需要安装在不同路径&#xff1b;安装Unity时不能有中文路径&#xff1b;Unity项目路径也不要有中文。 Scene面板 相当于拍电影的片场&#xff0c;Unity程…...

【CSS in Depth 2 精译_041】6.4 CSS 中的堆叠上下文与 z-index(上)

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09;第二章 相对单位&#xff08;已完结&#xff09;第三章 文档流与盒模型&#xff08;已完结&#xff09;第四章 Flexbox 布局&#xff08;已…...

uniapp微信小程序巧用跳转封装鉴权路由

1.这是封装的跳转方法&#xff1a; import store from "../stores/store";function Router(type, url, params) {const NoLoginPage [。。。。。];var queryString Object.keys(params).map((key) > ${key}${params[key]}).join("&");if (!NoLog…...

国外电商系统开发-运维系统开发

因项目运营环境在国外&#xff0c;所以必须将服务器选择国外&#xff0c;加上第一次运营国外项目。在两大趋势下&#xff0c;企业的运营方向必须通过大数据来分析及修正运营方向&#xff0c;加上后期服务器数量日益增多&#xff0c;如何有效的管理众多的服务器及验证运营方向&a…...

基于投影滤波算法的rick合成地震波滤波matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 RICK合成地震波模型 4.2 投影滤波算法原理 5.完整工程文件 1.课题概述 基于投影滤波算法的rick合成地震波滤波matlab仿真。分别通过标准的滤波投影滤波以及卷积滤波投影滤波对合成地震剖面进行滤波…...

【艾思科蓝】机器学习框架终极指南:PyTorch vs TensorFlow vs Keras vs Scikit-learn

第十届建筑、土木与水利工程国际学术会议(ICACHE 2024)_艾思科蓝_学术一站式服务平台 更多学术会议请看&#xff1a;学术会议-学术交流征稿-学术会议在线-艾思科蓝 目录 引言 1. PyTorch PyTorch的特点 PyTorch的用例 PyTorch的安装 PyTorch代码示例 2. TensorFlow …...

招联金融秋招内推2025

【投递方式】 直接扫下方二维码&#xff0c;或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus&#xff0c;使用内推码 igcefb 投递&#xff09; 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…...

遮罩解决图片悬浮操作看不到的情况

未悬浮效果 悬浮效果 如果仅仅是添加绝对定位&#xff0c;那么遇到白色图片&#xff0c;就会看不到白色字体。通过遮罩&#xff08;绝对定位透明度&#xff09;就可以解决这个问题。 <script setup> </script><template><div class"box"><…...

IoT网关的主要功能有哪些?天拓四方

在数字化浪潮席卷全球的今天&#xff0c;物联网&#xff08;IoT&#xff09;技术凭借其独特的优势&#xff0c;逐渐在各个领域展现出强大的生命力。而IoT网关&#xff0c;作为连接物理世界与数字世界的桥梁&#xff0c;其在物联网体系中的作用愈发凸显。 一、数据聚合与预处理…...

继承实现单例模式的探索(一)

前言 之前看到朋友采用继承的方式来实现单例模式&#xff0c;觉得很厉害&#xff0c;随后自己去探索了一番&#xff0c;以前实现单例模式都是把代码内联到具体的类中&#xff0c;这使得工程中每次需要使用单例模式时&#xff0c;都采用拷贝的方式&#xff0c;增加了很多冗余代码…...

【代码实现】opencv 高斯模糊和pytorch 高斯模糊

wiki百科 Gaussian Blur&#xff0c;也叫高斯平滑&#xff0c;是在Adobe Photoshop、GIMP以及Paint.NET等图像处理软件中广泛使用的处理效果&#xff0c;通常用它来减少图像噪声以及降低细节层次。 opencv实现 opencv实现高斯滤波有两种方式&#xff0c; 1、是使用自带的cv2…...

python基础语法2

文章目录 1.顺序语句2.条件语句2.1 语法格式 3.缩进与代码块4.空语句 pass5.循环语句5.1 while循环5.2 for循环 5.3 continue与break 1.顺序语句 默认情况下&#xff0c;python的代码都是按照从上到下的顺序依次执行的。 print(hello ) print(world)结果一定是hello world。写…...

linux第一课:下载与安装

这是我的个人复习笔记&#xff0c;草稿箱字太多会卡就发这了&#xff0c;欢迎大家阅读。 Kali Linux&#xff0c;黑客必备神器。跟着我&#xff0c;带你从入门到入狱&#xff01; 第一课&#xff0c;下载与安装。 第一步&#xff1a; 在官网下载Centos镜像&#xff1a;http…...

虚拟机添加共享文件夹后仍无法显示文件

参考: https://blog.csdn.net/Pretender_1205/article/details/134859089 进入/mnt/hgfs目录下执行 sudo mount -t fuse.vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other/mnt/hgfs 是挂载点&#xff0c;也可以修改为其他挂载点-o allow_other表示允许其他用户(普通用户)访问共…...

OSPF协议

基础知识 OSPF:开放式最短路径优先协议 (无类别链路状态IGP动态协议) OSPF的特点&#xff1a; 1.OSPF将自治系统划分为逻辑上的区域&#xff0c;使用LSA来发布路由信息&#xff0c;并通过OSPF报文在区域内路由器之间交互建立链路状态数据库和路由表 2.支持等开销的负载均衡…...

行为设计模式 -观察者模式- JAVA

观察者模式 一.简介二. 案例2.1 抽象主题&#xff08;Subject&#xff09;2.2 具体主题&#xff08;Concrete Subject&#xff09;2.3 抽象观察者&#xff08;Observer&#xff09;2.4 具体观察者&#xff08;Concrete Observer&#xff09;2.5 测试 三. 结论3.1 优缺点3.2 使用…...

在阿里工作是一种什么体验?

很多人都对在阿里工作感到好奇&#xff0c;今天就来给大家分享一下在阿里工作是一种什么体验~ 首先&#xff0c;先来介绍一下阿里的职位等级划分标准。 简单来讲&#xff0c;阿里的职位等级可以认为是 P 序列和 M 序列&#xff0c;但目前 M 序列已经不太对中下层员工开放了&…...

828华为云征文|华为云Flexus云服务器X实例——uniapp功能开发、搭建股票系统选择用什么服务器比较好?

在二次开发、安装搭建股票系统时&#xff0c;选择华为云Flexus X服务器是一个值得考虑的优质选项。以下是一些具体的建议&#xff1a; 测试环境&#xff1a;Linux系统CentOS7.6、宝塔、PHP7.3、MySQL5.7&#xff0c;根目录public&#xff0c;伪静态thinkphp&#xff0c;开启ssl…...