原生BBB系统框架介绍                      

说明分析基于bigbluebutton- 2.2-beta11版本,已忽略系统中flash的部分,只关注H5的实现。

BBB系统各模块介绍:

BigBluebutton 框架介绍

 

分析:服务器端存在多个模块,各模块之前通过redis pub通信,通信模型是基于事件的发布订阅机制,各模块订阅自己的通道 ,发布事件时发布到相应的通道。

 

注意:websocket的连接不是一有一条tcp直连,而是经过了nginx有两段tcp连接。

 

各模块在系统中的功能和作用:

  1. Bbb-html5模块:meteor客户端:负责业务的UI呈现,与用户交互实现业务场景的切换,与服务端交互实现各业务场景功能。与信令服务器交互推拉音视频流,与h5服务器交互申请改变数据库实现各子业务功能(投票,白板,聊天等),通过调用web-api实现文件上传,下载,转换等。

meteor服务端:nodejs进程,meteor工程服务端,通过websocket接收客户端请求,将相应请求分发出去并监听事件,改变mongo数据库并同步到客户端。

 

  1.  Nginx模块:根据http/https 中请求中的url将请求分发到对应的模块,分布式反射代理服务,静态htmlweb服务。
  2. Bbb-web模块:对外提供功能API,负责会议室管理,用户加入会议,文件管理(文件上传,下载,转换成幻灯片格式(通过调用第三方软件 实现转换 png,swf等))。

 

  1. Bbb-akka-apps: apps 的作用是沟通系统中各模块,与bbb-web , bbb-html5模块共同实现房间,用户及用户行为的管理。例如bbb-html5的各请求均发送到bbb-apps模块,bbb-apps再根据事件作数据合法,权限检测,通过后不需要第三方软件协助的事件(例如聊天,投票等功能)再通知到bbb-html5,需要第三方软件协助(例如静音功能需要转发等freeswitch)转发到相应模块再收到相应事件回应后再通知到html5模块。  
  2. 信令服务器模块,多个node js进程,整体功能就是媒体流的控制,客户端通过与信令服务器交互就可以实现流的推拉。它是通过控制 kurento 或freeswitch来最先实现流的转发。
  3. Kurento server模块,通过rtp,webrtc等技术实现流的转发。
  4. Bbb-akka-fsel ,通过sip信令控制freeswitch控制声音流(静音等功能),得到音频流状态(谁正在说话功能)
  5. Freeswitch。 音频会议室管理,用户加入,退出,静音等。 都是控制音频流的分发与合成来实现的。
  6. Bbb-transcode模块: 通过调用ffmpeg实现流转码功能,流的封包格式转换等。

  例如 rtmp 转rtp , rtp 转rtmp等。

  1. bbb-html5模块通过mongod保存数据。
  2. Redis-server :用于实现进程音的通信,通信模型是基于事件的发布订阅机制,各模块订阅自己的通道 ,发布事件时发布到相应的通道。
  3. Bbb-webhooks模块,可以将系统中的各种事件通过http post的形式发送出去,开发者指定一个自己的url ,就能拿到系统中的所有事件了。
  4. Etherpad模块,开源的共享笔记应用,实现bbb系统中共享笔记的功能。
  5. Bbb-demo模块,简单的demo jsp页面,通过调用web-api实现房间的创建和用户的加入并跳转到 bbb-html5页面中去。
  6. Bbb-record-playback:录制与回放模块,通过对bbb系统中所有事件作处理,对录下的媒体流作处理,在会议结束后通过UI直观的方式来展示会议过程中所有发生的事件(包括媒体部分)。

 

 

Ps时看到的BBB进程:
bigblue+  java   bbb-akaa-apps
freeswitch 
bigblue+  java  bbb-akaa-fsel 
bigblue+  java  bbb-akaa-transcode
root     nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
tomcat7 /usr/lib/jvm/default-java/bin/java 
bigblue+  /bin/bash /usr/share/bbb-web/run-prod.sh
etherpad  /usr/bin/node node_modules/ep_etherpad-lite/node/server.js
bigblue+  java -Dgrails.env=prod -Dserver.port=8090 
kurento  /usr/bin/kurento-media-server
redis   /usr/bin/redis-server 127.0.0.1:6379
mongodb   /usr/bin/mongod --config /usr/share/meteor/bundle/mongo-ramdisk.conf 
bigblue+   /usr/lib/libreoffice/program/soffice.bin--accept=socket
bigblue+  /usr/bin/node server.js
bigblue+  /usr/bin/node ./lib/mcs-core/process.js ./lib/mcs-cor
bigblue+ /usr/bin/node  ./lib/screenshare/ScreenshareProcess ./
bigblue+  /usr/bin/node  ./lib/video/VideoProcess.js ./lib/video
bigblue+  /usr/bin/node  ./lib/audio/AudioProcess.js ./lib/audio
 
监听的二级目录名和商端口:
/html5client 3000
"^\/pad\/p\/(\w+)$" , /pad  , /pad/socket.io , /static            9001  etherpad
 
/playback/presentation   /var/bigbluebutton/index
/presentation              /var/bigbluebutton/published/index
        location /playback/presentation/playback.html {
                 return 301 /playback/presentation/0.81/playback.html?$query_string;
/ws              7443
/bigbluebutton  8090
/bbb-webrtc-sfu   3008
/demo                8080

 

BBB系统各模块总结:

通过模块图可以看到,bbb本身模块众多,还基于一些第三方软件 。实际上bbb系统每个模块本身的代码量并不大。 核心功能应该是会议室管理,人员管理,音视频通信,所以这些主要是分析 bbb-html5,bbb-web,bbb-akka-apps,bbb-webrtc-sfu 以及了解第三方软件 kruento,freeswitch。

 

 

 

bbb-akka-apps 模块分析:

BigBluebutton 框架介绍

 

 

在分析这个模块时,首先找到这个模块程序的入口程序 ,它是 Boot.scala中的 Boot. 这是由SprintBoot这个框架决定的。

 

在分析Boot之前 ,要先了解akka中的 actor 和 bus 的概念。

 

object Boot extends App with SystemConfiguration {

 

  implicit val system = ActorSystem("bigbluebutton-apps-system")

  implicit val executor = system.dispatcher

 

  val logger = Logging(system, getClass)

 

  val eventBus = new InMsgBusGW(new IncomingEventBusImp())

 

  val outBus2 = new OutEventBus2

  val recordingEventBus = new RecordingEventBus

 

  val outGW = new OutMessageGatewayImp(outBus2)

 

  val redisPublisher = new RedisPublisher(system, "BbbAppsAkkaPub")

  val msgSender = new MessageSender(redisPublisher)

 

  val redisRecorderActor = system.actorOf(RedisRecorderActor.props(system), "redisRecorderActor")

 

  recordingEventBus.subscribe(redisRecorderActor, outMessageChannel)

  val incomingJsonMessageBus = new IncomingJsonMessageBus

 

  val bbbMsgBus = new BbbMsgRouterEventBus

 

  val fromAkkaAppsMsgSenderActorRef = system.actorOf(FromAkkaAppsMsgSenderActor.props(msgSender))

  val analyticsActorRef = system.actorOf(AnalyticsActor.props())

  outBus2.subscribe(fromAkkaAppsMsgSenderActorRef, outBbbMsgMsgChannel)

  outBus2.subscribe(redisRecorderActor, recordServiceMessageChannel)

 

  outBus2.subscribe(analyticsActorRef, outBbbMsgMsgChannel)

  bbbMsgBus.subscribe(analyticsActorRef, analyticsChannel)

 

  val bbbActor = system.actorOf(BigBlueButtonActor.props(system, eventBus, bbbMsgBus, outGW), "bigbluebutton-actor")

  eventBus.subscribe(bbbActor, meetingManagerChannel)

 

  val redisMessageHandlerActor = system.actorOf(ReceivedJsonMsgHandlerActor.props(bbbMsgBus, incomingJsonMessageBus))

  incomingJsonMessageBus.subscribe(redisMessageHandlerActor, toAkkaAppsJsonChannel)

 

  val redisSubscriberActor = system.actorOf(AppsRedisSubscriberActor.props(system, incomingJsonMessageBus), "redis-subscriber")

}

 

首先看Boot的最后一句:它在构造 AppsRedisSubscriberActor 时会调用 subscript()订阅相关的通道,收到外部的事件,然后传入apps内部。

 

具体细节:

AppsRedisSubscriberActor 继承了 RedisSubscripberProvider(位置在bbb-common-message/sr/main/scala/org/bigbluebutton/common2/redis/RedisSubScriberProvider.scala)

 

看 RedisSubscriterProvider的订阅方法:

BigBluebutton 框架介绍

 

可以看到它是用redis的subscripe 订阅相关的通道()。

toAkkaTranscodeRedisChannel,fromVoiceConfRedisChannel,toAkkaAppsJsonChannel

从名称可以看到分别是 转码相关,声音相关,和指发到这模块的通道。

 

在收到消息后利用incomingJsonMessageBus将消息发布出去,现在就到了apps模块内部来处理这些消息了。 代码如图所示。

BigBluebutton 框架介绍

 

再分析处理接着处理消息的 actor ReceivedJsonMsgHandlerActor.

这个actor 也只是消息根据类型分发到eventBus的 不同通道中,在用户真正进入到会议室之前 的发布到了meetingManagerChanne通道,比如会议室的创建,用户进入时的验证等消息,用户进入到会议室之后的操作发布到了以会议室ID命名的通道。比如用户聊天 ,投票等消息。 还有声音相关的被分发 voiceConf 的通道。

 

BigBluebutton 框架介绍多发了一个 anylyticsEvent事件,这个事件主要是用来记录的,处理这个事件的actor只是将事件存入到Log文件中,只是用于记录事件log. 这个事件先不做分析。

 

消息现在到了eventbus ,接着往下分析eventbus中消息的处理。

 

BigBluebutton 框架介绍

 

在处理创建会议室时又使evetbus订阅了 会议室id,voiceCOnf,screensahreConf通道。 也就是说在用户进入后的所有操作的消息处理都在 RunningMeeting 的 MeetingActor 中。

消息的处理过程大多数是权限检测,数据检测等,然后通过后在apps模块新增相应的数据。 然后再将处理结果 发送出去。

 

再来分析发送消息出去的过程:

 

通过outGW 发送到 outBus2 的 meetingManagerChannel,然后再到 FromAkkaAppsMsgSenderActor 通过 msgSender 发送到redis 中去。

 

房间创建,用户加入过程详细分析:

房间创建,用户加入时序图:

BigBluebutton 框架介绍

分析源码时整理的函数调用流程图:

BigBluebutton 框架介绍

 

 

从时序图中可以看到完成房间创建,用户加入是bbb-web,bbb-apps,html5三个模块共同协助的结果。他们之前通信消息应该有统一的格式,实际上bbb系统消息都有统一的格式,所有各模块之间才能顺利沟通,消息的创建是由bbb-common-web,bbb-common-message的代码完成的。

事件消息数据示例:

 

 

注册用户请求消息:

{

    "payload": {

        "name": "RED",

        "role": "MODERATOR",

        "user_id": "rg74zt7x78oe",

        "meeting_id": "183f0bf3a0982a127bdb8161e0c44eb696b3e75c-1397936286394",

        "external_user_id": "rg74zt7x78oe"

    },

    "header": {

        "timestamp": 1193516905118123,

        "name": "register_user_request"

    }

}

 

 

用户加入消息

{

    "payload": {

        "recorded": false,

        "meeting_id": "183f0bf3a0982a127bdb8161e0c44eb696b3e75c-1397936286394",

        "user": {

            "voice_user": {

                "talking": false,

                "joined": false,

                "muted": false,

                "caller_id_name": "RED",

                "user_id": "rg74zt7x78oe",

                "locked": false,

                "web_user_id": "rg74zt7x78oe",

                "caller_id_num": "RED"

            },

            "name": "RED",

            "phone_user": false,

            "has_stream": false,

            "webcam_stream": "",

            "role": "MODERATOR",

            "user_id": "rg74zt7x78oe",

            "locked": false,

            "raise_hand": false,

            "presenter": false,

            "external_user_id": "rg74zt7x78oe"

        }

    },

    "header": {

        "timestamp": 1193517200604687,

        "name": "user_joined_message"

    }

}

 

 

从消息格式可以看出 header中标明了消息类型,payload中是消息的数据。

 

从时序图的分析中可以看到 bbb-web,bbb-apps,bbb-html5模块都存了会议,用户相关的所有数据,bbb-web,bbb-apps是存放在内存中,bbb-html5是存放在mongodb,并放入了内存中。

 

bbb-apps是处理各种消息的核心,所有的消息都会通过apps,apps还会将消息保存到redisdb中,可以用户之后回放会议使用。 Bbb-apps可以说是所有功能的处理中心,因为所有事件都需要经过apps确认,apps会对这些事件进行权限,是否合理,或者转发到相应模块去处理。整套BBB系统是通过消息来携同各个模块来转起来,所以bbb-apps应该是消息控制中心。

 

 

相关文章: