项目描述 : 基于Nginx实现基本的点播和直播功能,基于WebSocket实现了IM在线聊天系统
项目亮点:
-
对接短信验证码实现手机号注册登录,并使用Cosid框架生成分布式唯一ID
-
引入rtmp模块实现视频点播和直播功能,并通过心跳机制来检测用户行为来减少网络资源消耗
-
使用Rocket MQ实现IM系统的消息处理和转发功能,解决了Session无法序列化共享的问题
-
使用Redis中间件解决跨进程的消息推送服务,实现多个IMServe的数据共享
-
实现了IM系统的水平扩展,简单设计与实现了IM集群架构
怎么对接验证码的?
使用第三方云服务厂商SDK,直接配置点账号,令牌什么的就行了
先根据用户手机号在redis中找一下是否存在,如果存在给用户一个申请频繁的提示
没有的话就在redis中保存用户的手机号和随机的一个验证码,并设置过期时间
然后发送这个验证码
为什么要使用分布式唯一ID?
大的方面来说,随着应用越来越大,通常需要通过集群化部署来分摊计算、存储压力。 应用服务的无状态设计使其具备了伸缩性
但对于有状态的数据库就不那么容易了,此时数据库变成系统的性能瓶颈是显而易见的。所以通常需要分库分表,而分片算法就需要这种分布式唯一ID的设计
还有你像因为是微服务,将来可能部署多个实例,所以需要分布式唯一ID
为什么使用Cosid框架?
我先讲一下传统的唯一主键生成策略
第一种:数据库自增:使用简单,很多框架都有封装,但是跟当前业务不符合,而且数据库压力大(高并发请求下数据库连接数变多,而且涉及到表锁或者行锁的竞争导致性能下降,还有也可能受到网络延迟的影响)
第二种:应用自己生成:比如UUID使用简单,但是字符串对数据库不太友好,其他的像雪花算法可能出现时钟回拨问题,工作进程位不好设置,而且序列位为不递增
第三种:使用美团的Leaf框架,双Buffer,10%的阈值去申请,而且一次申请多个ID,减少网络请求,但是美团这个强依赖于DB,而且不灵活(水平扩展),所以使用Cosid框架。
Cosid框架使用比较简单,支持多种分布式ID生成算法(SnowflakeId、SegmentId、SegmentChainId),而且可以设置Buffer的阈值什么的,比较灵活
怎么实现基于Nginx的点播和直播的?
Java的话其实是不适合做音视频项目的,因为音视频处理需要对底层做很多数据处理,Java是通过JVM虚拟机来和底层交互的,所以通常需要借助第三方的框架或者模块来实现
常见的流媒体直播协议主要有RTSP、RTMP、和HLS
- RTSP:是一个基于TCP的流媒体传输协议,用来控制流媒体数据的传输,它定义了如何初始化和控制多媒体的传输,RTSP通常延迟较低,但是技术实现比较复杂,通常用于防盗视频监控场景。JavaCV 库集成 RTSP 流实现
- RTMP:主要用于 Flash 应用中的直播和点播,在PC端有很大的市场,应用广泛。所以选择了这个
- HLS:苹果公司的基于HTTP的视频传输协议,兼容性强,它最主要的是使用了分片,它需要将直播下载为一个个分片的文件才能播放,所以延迟可能高一点
下载nginx和 Nginx 的第三方模块:nginx-rtmp
正常安装成功后,会在/user/local下有一个nginx目录
然后一起编译安装,然后配置nginx,在rtmp 块下配置路径什么的
直播的话配置hls地址,切片缓存目录保存.ts文件
然后使用OBS推流,填写hls地址,不同的秘钥对应不同的直播间,然后客户端拉流(地址上加上秘钥)
使用http协议也可以拉流,地址上是索引文件
客户端是使用video.js来配合http协议的拉流来读取,会有跨域问题,所以考虑容器等
可以使用ffmpeg来对音视频进行格式转换
点播的话,把视频文件单独作为一个条目,然后http请求单独来访问
直播:
怎么样过心跳检测来减少网络资源消耗?
有一个map记录每一个Session给服务器发消息的时间
就是后端每隔几秒去检测当前用户有没有发过消息,如果没有就关闭它的链接
IM系统为什么要进行水平扩展?
IM系统是一个微服务,将来部署多个实例,也就是水平扩展。主要是为了提高系统的高连接下的扩展性和可用性
IM系统怎么实现水平扩展的?
思路是都注册到nacos上面,然后写一个服务专门去查询这些实例,然后根据负载均衡或者别的策略返回一个实例
因为这个接口是开放的,所以加了一层token鉴权,服务除了返回服务地址外,还会返回一个随机Token存入redis中,Val为用户ID,在前端与IM系统建立连接的时带上token,IM系统去redis中验证Token是否合法,不合法就拒绝请求
IM系统为什么要进行集群扩展?
虽然IMServer实现了请求接入时的负载均衡功能,但是每一个IMServer的ConnectionManager(链接管理器)中保存的Session缓存和房间与用户数据信息还只是保存在每一个应用的内存中,因此如果多个前端的长连接建立在不同的IMServer上,那么就算它们进入了同一个直播间,也是无法实现跨进程的消息推送的。因此还要实现多个IMServer服务实例的集群化设计
IM系统怎么进行集群扩展?
集群扩展就是引入第三方组件MQ,讲所有的消息推到MQ上,然后写一个单独的Server服务单独去拉取MQ上的消息,同时进行一些处理,设置每隔5条消息推送到这些所有的实例上
Nginx是什么?
是一个高性能的HTTP和反向代理服务器,可以作为静态内容的Web服务器
可以做反向代理服务器,负载均衡,API网关
反向代理是相对于正向代理来说的。
正向代理是在客户端和服务端之间,客户端的请求首先发送到正向代理服务器,然后由代理服务器向目标服务器转发请求,并获取响应后返回给客户端。
反向代理是位于服务端,客户端并不直接与目标服务器通信,而是将请求发送到反向代理服务器,然后由反向代理将请求转发到后端的一组服务器之一,并从选定的服务器获取响应后返回给客户端。
主要区别是客户端知不知道它正在与代理服务器通信。并且正向代理更侧重于客户端的需求,而反向代理更侧重于服务器端的需求。
IM系统
消息转发:一个Session代表了服务端与客户端建立的一个长连接,将Session保存下来,就可以实现长连接的复用,进行消息转发
通过一个全局容器将所有客户端的Session保存下来,实现消息转发
对于webSocket的controller来说,一个线程对应一个controller
关于房间路由:
定义消息体:
前端消息推送处理:
mitt:
系统结构: