4 Star 6 Fork 5

winlinvip / owt-docker

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

OWT-DOCKER

Docker for owt-server from Ubuntu18(ubuntu:bionic).

  • registry.cn-hangzhou.aliyuncs.com/ossrs/owt:4.3:内网演示方式Usage: HostIP,配置好了docker-host域名。
  • registry.cn-hangzhou.aliyuncs.com/ossrs/owt:config:修改了端口和脚本,参考Port RangeAuth Update
  • registry.cn-hangzhou.aliyuncs.com/ossrs/owt:pack:完成了pack.js步骤,打包好了OWT。
  • registry.cn-hangzhou.aliyuncs.com/ossrs/owt:build:完成了build.js步骤,编译好了OWT。
  • registry.cn-hangzhou.aliyuncs.com/ossrs/owt:system:完成了installDepsUnattended.sh步骤,安装好了依赖。

Note: 针对Docker下部署和使用OWT,我们修改了一些代码和配置,参考Here

以MacPro为例,如何使用镜像搭建Demo,推荐使用Usage: HostIP,提供了几种常见的方式:

  • 在内网用镜像搭建OWT,使用脚本自动获取IP,自动修改OWT配置文件中的IP,参考Usage: HostIP
  • 在内网使用镜像快速搭建OWT,需要修改IP,参考Usage
  • 有公网IP或域名时,用镜像搭建OWT服务,参考Usage: Internet

下面是本文涉及的重点:

  • OWT开发环境搭建,本机快速部署,不用改IP,参考Usage: HostIP
  • OWT本机修改,可修改C++代码,在Docker中编译和运行,参考Develop
  • OWT调试js和WebRTC的C++代码,参考Debug
  • OWT几组性能数据,WebRTC性能不高,参考Performance
  • OWT存在的一些问题,参考Issues
  • OWT的程序结构,使用Nodejs调用C++代码,参考CodeNodejs
  • OWT的代码分析,参考CodeVideo

Usage

下面我们以MacPro为例,如何使用镜像搭建内网Demo,其他OS将命令替换就可以。

>>> Step 0: 当然你得有个Docker。

可以从docker.io下载一个,安装就好了。 执行docker version,应该可以看到Docker版本:

Mac:owt-docker chengli.ycl$ docker version
Client:
 Version:	17.12.0-ce
Server:
  Version:	17.12.0-ce

>>> Step 1: 通过Docker镜像,启动OWT环境。

docker run -it -p 3004:3004 -p 3300:3300 -p 8080:8080 -p 60000-60050:60000-60050/udp \
    registry.cn-hangzhou.aliyuncs.com/ossrs/owt:config bash

Note: Docker使用的版本是owt-server 4.3, owt-client 4.3, IntelMediaSDK 18.4.0.

Note: OWT需要开一系列范围的UDP端口,docker映射大范围端口会有问题,所以我们只指定了50个测试端口,已经在镜像中修改了配置,参考Port Range

Note: 针对Docker下部署和使用OWT,我们修改了一些代码和配置,参考Here

>>> Step 2: 设置OWT的IP信息,设置为Mac的IP地址。也可以自动获取和设置IP,参考Usage: HostIP

# vi dist/webrtc_agent/agent.toml
[webrtc]
network_interfaces = [{name="eth0",replaced_ip_address="192.168.1.4"}]  # default: []

# vi dist/portal/portal.toml
[portal]
ip_address = "192.168.1.4" #default: ""

>>> Step 3: 输入命令,初始化OWT和启动服务。

(cd dist && ./bin/init-all.sh && ./bin/start-all.sh)

>>> Step 4: 大功告成。

打开OWT的默认演示页面,私有证书需要选择Advanced => Proceed to xxx

由于证书问题,第一次需要在浏览器,先打开OWT信令服务(Portal)页面(后续就不用了):

访问管理后台,注意启动服务时有个sampleServiceId和sampleServiceKey,打开页面会要求输入这个信息:

Note: 我们也可以使用域名来访问OWT服务,这样就不用每次IP变更后修改配置文件,参考Usage: HostIP

Note: 目前提供OWT 4.3的镜像开发环境,若需要更新代码需要修改Dockerfile,或者参考Deubg重新编译。

还可以尝试其他方式,比如:

  • 在内网使用镜像快速搭建OWT,需要修改IP,参考Usage
  • 在内网用镜像搭建OWT,使用脚本自动获取IP,自动修改OWT配置文件中的IP,参考Usage: HostIP
  • 有公网IP或域名时,用镜像搭建OWT服务,参考Usage: Internet

Usage: HostIP

在之前Usage中,我们说明了如何在内网用镜像快速搭建OWT服务,但需要修改OWT的配置文件。 这里我们说明如何使用脚本自动获取IP,自动修改OWT配置文件中的IP。

下面我们以MacPro为例,如何使用镜像搭建内网Demo,其他OS将命令替换就可以。

>>> Step 0: 当然你得有个Docker。

可以从docker.io下载一个,安装就好了。 执行docker version,应该可以看到Docker版本:

Mac:owt-docker chengli.ycl$ docker version
Client:
 Version:	17.12.0-ce
Server:
  Version:	17.12.0-ce

>>> Step 1: 先获取宿主机的IP,该IP需要在访问的机器上能Ping通。

HostIP=`ifconfig en0 inet| grep inet|awk '{print $2}'` &&
echo "" && echo "" && echo "" && echo "OWT演示页面:" && echo "  https://$HostIP:3004/" &&
echo "第一次需要先访问信令(Portal):" && echo "  https://$HostIP:8080/socket.io/?EIO=3&transport=polling&t=N2UmsIn"

或者直接设置为自己的IP:

HostIP="192.168.1.4" &&
echo "" && echo "" && echo "" && echo "OWT演示页面:" && echo "  https://$HostIP:3004/" &&
echo "第一次需要先访问信令(Portal):" && echo "  https://$HostIP:8080/socket.io/?EIO=3&transport=polling&t=N2UmsIn"

>>> Step 2: 通过Docker镜像,启动OWT环境。

HostIP=`ifconfig en0 inet| grep inet|awk '{print $2}'` &&
docker run -it -p 3004:3004 -p 3300:3300 -p 8080:8080 -p 60000-60050:60000-60050/udp \
    --env DOCKER_HOST=$HostIP registry.cn-hangzhou.aliyuncs.com/ossrs/owt:4.3 bash

Note: Docker使用的版本是owt-server 4.3, owt-client 4.3, IntelMediaSDK 18.4.0.

Note: OWT需要开一系列范围的UDP端口,docker映射大范围端口会有问题,所以我们只指定了50个测试端口,已经在镜像中修改了配置,参考Port Range

Note: OWT对外提供了信令和媒体服务,所以需要返回可外部访问的IP地址,我们通过环境变量传递给Docker,参考Docker Host IP

Note: 针对Docker下部署和使用OWT,我们修改了一些代码和配置,参考Here

>>> Step 3: 输入命令,初始化OWT和启动服务。

(cd dist && ./bin/init-all.sh && ./bin/start-all.sh)

>>> Step 4: 大功告成。

打开OWT的默认演示页面,私有证书需要选择Advanced => Proceed to 192.168.1.4 (unsafe)

由于证书问题,第一次需要在浏览器,先打开OWT信令服务(Portal)页面(后续就不用了):

访问管理后台,注意启动服务时有个sampleServiceId和sampleServiceKey,打开页面会要求输入这个信息:

Note: 我们使用域名来访问OWT服务,这样宿主机IP变更后,只需要执行脚本就可以,参考Docker Host IP

Note: 目前提供OWT 4.3的镜像开发环境,若需要更新代码需要修改Dockerfile,或者参考Deubg重新编译。

还可以尝试其他方式,比如:

  • 在内网使用镜像快速搭建OWT,需要修改IP,参考Usage
  • 在内网用镜像搭建OWT,使用脚本自动获取IP,自动修改OWT配置文件中的IP,参考Usage: HostIP
  • 有公网IP或域名时,用镜像搭建OWT服务,参考Usage: Internet

Usage: Internet

Remark: 下面说明公网IP或域名搭建OWT环境,若在内网或本机使用Docker快速搭建OWT开发环境,参考Usage:

>>> Step 1: 通过Docker镜像,启动OWT环境。

docker run -it -p 3004:3004 -p 3300:3300 -p 8080:8080 -p 60000-60050:60000-60050/udp \
    registry.cn-hangzhou.aliyuncs.com/ossrs/owt:config bash

Note: Docker使用的版本是owt-server 4.3, owt-client 4.3, IntelMediaSDK 18.4.0.

Note: OWT需要开一系列范围的UDP端口,docker映射大范围端口会有问题,所以我们只指定了50个测试端口,已经在镜像中修改了配置,参考Port Range

Note: 针对Docker下部署和使用OWT,我们修改了一些代码和配置,参考Here

>>> Step 2: 配置公网IP或域名,参考Use Internet Name

# vi dist/webrtc_agent/agent.toml
[webrtc]
network_interfaces = [{name="eth0",replaced_ip_address="182.28.12.12"}]  # default: []

# vi dist/portal/portal.toml
[portal]
ip_address = "182.28.12.12" #default: ""

>>> Step 3: 输入命令,初始化OWT和启动服务。

(cd dist && ./bin/init-all.sh && ./bin/start-all.sh)

Remark: 注意会有个提示是否添加MongoDB账号,可以忽略或写No(默认5秒左右就会忽略)。

>>> Step 4: 大功告成。

打开OWT的默认演示页面,私有证书需要选择Advanced => Proceed to xxx

由于证书问题,第一次需要在浏览器,先打开OWT信令服务(Portal)页面(后续就不用了):

访问管理后台,注意启动服务时有个sampleServiceId和sampleServiceKey,打开页面会要求输入这个信息:

Note: 目前提供OWT 4.3的镜像开发环境,若需要更新代码需要修改Dockerfile,或者参考Deubg重新编译。

还可以尝试其他方式,比如:

  • 在内网使用镜像快速搭建OWT,需要修改IP,参考Usage
  • 在内网用镜像搭建OWT,使用脚本自动获取IP,自动修改OWT配置文件中的IP,参考Usage: HostIP
  • 有公网IP或域名时,用镜像搭建OWT服务,参考Usage: Internet

Develop

如果需要修改代码后编译:

  1. 可以先将Docker代码拷贝出来。不用每次都拷贝,只有第一次需要拷贝。
  2. 接着在本地修改OWT代码。可以用IDE等编辑器编辑代码,比较方便。
  3. 然后挂载本地目录到Docker。挂载后,会以本地目录的文件,代替Docker中的文件。
  4. 最后在Docker编译和运行OWT。如果修改的是JS,可以直接重启服务生效。

>>> Step 1: 将Docker代码拷贝出来。

首先,需要先运行Docker:

docker run -it registry.cn-hangzhou.aliyuncs.com/ossrs/owt:4.3 bash

然后,可以用docker ps,获取运行的容器ID,比如是75647b1a7b16

Mac:owt-docker chengli.ycl$ docker ps
CONTAINER ID        IMAGE
75647b1a7b16        registry.cn-hangzhou.aliyuncs.com/ossrs/owt:4.3

接着,从运行的容器75647b1a7b16中拷贝OWT代码:

mkdir -p ~/git/owt-docker && cd ~/git/owt-docker &&
docker cp 75647b1a7b16:/tmp/git/owt-docker/owt-client-javascript-4.3 .
docker cp 75647b1a7b16:/tmp/git/owt-docker/owt-server-4.3 .

这样,我们就有了OWT 4.3的代码,接下来就可以在本地修改代码了。

Note: 当然,也可以直接从OWT下载最新代码,映射到Docker后编译执行,注意只映射source目录到Docker。

>>> Step 2: 在本地修改OWT代码。

我们举个栗子,我们修改OWT,支持使用环境变量DOCKER_HOST来指定portal.ip_address

Note: Docker运行时,可以通过--env DOCKER_HOST='192.168.1.4'设置环境变量,这样在Docker中就可以通过获取环境变量来获取IP。

修改文件source/portal/index.js,参考118d225f

if (config.portal.ip_address.indexOf('$') == 0) {
    config.portal.ip_address = process.env[config.portal.ip_address.substr(1)];
    log.info('ENV: config.portal.ip_address=' + config.portal.ip_address);
}

修改文件source/portal/portal.toml,将信令Portal的ip_address引用环境变量:

[portal]
ip_address = "$DOCKER_HOST" #default: ""

Remark: 这里我们只修改了JS代码,也可以修改c++代码。

>>> Step 3: 挂载本地目录到Docker。

启动Docker,并将本地目录挂载到Docker:

cd ~/git/owt-docker/owt-server-4.3 &&
HostIP=`ifconfig en0 inet| grep inet|awk '{print $2}'` &&
docker run -it -p 3004:3004 -p 3300:3300 -p 8080:8080 -p 60000-60050:60000-60050/udp \
    --env DOCKER_HOST=$HostIP -v `pwd`:/tmp/git/owt-docker/owt-server-4.3 \
    registry.cn-hangzhou.aliyuncs.com/ossrs/owt:4.3 bash

>>> Step 4: 在Docker编译和运行OWT。

若修改了c++代码,则需要编译OWT(若没有修改则可以忽略):

./scripts/build.js -t all --check --debug

Remark: 注意我们加了debug参数,编译出调试版本。

这个例子中,我们只修改了JS文件,所以直接打包就可以:

./scripts/pack.js -t all --debug --addon-debug --install-module --sample-path $CLIENT_SAMPLE_PATH

Remark: 注意我们加了debug参数,打包调试版本。

为了保持命令行一直,我们将dist-debug链接为dist

ln -sf dist-debug dist

可以看到,dist/portal/portal.tomldist/portal/index.js这两个文件都更新了。

启动服务后,就可以看到修改生效了:

(cd dist && ./bin/init-all.sh && ./bin/start-all.sh)

Debug

供Debug用的镜像:

  • registry.cn-hangzhou.aliyuncs.com/ossrs/owt:debug:内网演示方式Usage: HostIP,配置好了docker-host域名。
  • registry.cn-hangzhou.aliyuncs.com/ossrs/owt:config-debug:修改了端口和脚本,参考Port RangeAuth Update
  • registry.cn-hangzhou.aliyuncs.com/ossrs/owt:build-debug:完成了build.js步骤,编译好了OWT。
  • registry.cn-hangzhou.aliyuncs.com/ossrs/owt:system:完成了installDepsUnattended.sh步骤,安装好了依赖。

Note: 针对Docker下调试OWT,我们修改了一些代码和配置,参考Here

我们举个例子,调试OWT中的WebRTC Agent的代码。

>>> Step 0: 一定要使用调试版本的镜像。

为了方便调试,请使用调试镜像registry.cn-hangzhou.aliyuncs.com/ossrs/owt:debug,我们修改了几个地方:

  • 设置WebRTC Agent的进程数目为1,可以直接调试这个进程,不然多个进程每个进程都要设置断点,会比较麻烦(也可以调试)。
  • 设置nodeManager的超时时间为3000秒(即50分钟),默认是3秒,所以很容易在设置断点或单步运行时进程被杀掉,导致调试失败。
  • 日志级别全部设置为DEBUG,会显示更多的详细的日志,文件为log4js_configuration.json
  • 设置amqp_client的超时时间为2000秒(即33分钟),默认是2秒,所以会在调试时导致各种超时。

推荐使用debug镜像启动,若不使用debug镜像,你也可以手动修改你的OWT,改动参考这里

# 编译OWT时使用特殊的参数
./scripts/build.js -t all --check --debug

# vi dist/webrtc_agent/agent.toml +3
[agent]
maxProcesses = 1 #default: 13
prerunProcesses = 1 #default: 2

# vi dist/webrtc_agent/log4js_configuration.json +13
"ClusterWorker": "DEBUG",
"LoadCollector": "DEBUG",
"AmqpClient": "DEBUG",
"WorkingJS": "DEBUG",
"NodeManager": "DEBUG",
"WebrtcNode": "DEBUG",
"WrtcConnection": "DEBUG",
"Connection": "DEBUG",
"Sdp": "DEBUG",
"WorkingAgent": "DEBUG",
"Connections": "DEBUG",
"InternalConnectionFactory": "DEBUG"

# vi dist/webrtc_agent/nodeManager.js +125
child.check_alive_interval = setInterval(function() {
}, 3000000);

# vi dist/webrtc_agent/amqp_client.js +10
var TIMEOUT = 2000000;

Note: 如果需要调试其他模块,也需要修改这些参数。

Remark: 页面超时是由后端决定的,只需要修改后端的amqp_client.js的超时就可以。

>>> Step 1: 启动debug镜像。

启动Docker,添加gdb需要的参数--privileged

HostIP=`ifconfig en0 inet| grep inet|awk '{print $2}'` &&
docker run -it -p 3004:3004 -p 3300:3300 -p 8080:8080 -p 60000-60050:60000-60050/udp \
    --privileged --env DOCKER_HOST=$HostIP \
    registry.cn-hangzhou.aliyuncs.com/ossrs/owt:debug bash

当然,若需要挂载本地目录,可以按照上一步修改本地代码,或者从debug镜像将代码拷贝出来,然后执行:

cd ~/git/owt-docker/owt-server-4.3 &&
HostIP=`ifconfig en0 inet| grep inet|awk '{print $2}'` &&
docker run -it -p 3004:3004 -p 3300:3300 -p 8080:8080 -p 60000-60050:60000-60050/udp \
    --privileged --env DOCKER_HOST=$HostIP -v `pwd`:/tmp/git/owt-docker/owt-server-4.3 \
    registry.cn-hangzhou.aliyuncs.com/ossrs/owt:debug bash

启动OWT服务:

(cd dist && ./bin/init-all.sh && ./bin/start-all.sh)

>>> Step 2: 启动GDB调试WebRTC Agent进程。

启动GDB调试,并Attach调试WebRTC Agent的进程:

gdb --pid `ps aux|grep webrtc|grep workingNode|awk '{print $2}'`

然后设置断点,比如可以设置在函数上,或者在文件的某一行:

b WebRtcConnection.cc:346
c

Note: 设置断点后,执行continue或者c,继续跑程序。

>>> Step 3: 打开页面,命中断点。

打开页面,就会进入断点了:

Thread 1 "node" hit Breakpoint 1, WebRtcConnection::addRemoteCandidate (info=...) at ../WebRtcConnection.cc:313
313	  WebRtcConnection* obj = Nan::ObjectWrap::Unwrap<WebRtcConnection>(info.Holder());
(gdb) bt
#0  0x00007fe00d7affac in WebRtcConnection::addRemoteCandidate(Nan::FunctionCallbackInfo<v8::Value> const&) (info=...) at ../WebRtcConnection.cc:313
#1  0x00007fe00d7a9243 in Nan::imp::FunctionCallbackWrapper(v8::FunctionCallbackInfo<v8::Value> const&) (info=...)
    at ../../../../../node_modules/nan/nan_callbacks_12_inl.h:179
#2  0x000055c7c8302d0f in v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) ()
#3  0x000055c7c836bb62 in  ()

GDB是非常强大的调试工具,详细命令参考Debugging with GDB

Note: 也可以使用node inspect xxx.js调试js程序。

Remark: OWT使用Nodejs的NAN调用C++代码,调试原理参考CodeNodejs,代码结构参考CodeNodejs

Dependencies

OWT会安装很多依赖的库,详细可以参考Dockerfile中安装的依赖。

这些代码和依赖都会在docker中,下载代码包括:

  • node_modules/nan
  • build, 734M
    • build/libdeps/ffmpeg-4.1.3.tar.bz2
    • build/libdeps/libnice-0.1.4.tar.gz
    • build/libdeps/openssl-1.0.2t.tar.gz
    • build/libdeps/libsrtp-2.1.0.tar.gz
  • third_party, 561M
    • third_party/quic-lib, 8.4M
    • third_party/licode, 34M
    • third_party/openh264, 33M
    • third_party/SVT-HEVC, 39M
    • third_party/webrtc, 448M

Port Range

Docker由于需要映射端口,所以如果需要开特别多的UDP端口会有问题,Mac下的Docker能开50个左右的UDP端口,测试是够用了。

我们在镜像中已经修改了配置文件,将端口范围改成了60000-60050/udp,如果有需要可以自己改:

# vi dist/webrtc_agent/agent.toml
[webrtc]
maxport = 60050 #default: 0
minport = 60000 #default: 0

Note: 注意别改错了,还有另外个地方也有这个配置,[internal]这个是配置集群的(内部传输的端口比如webrtc-agent和video-agent之间的传输端口),单个Docker不用修改。

Docker Host IP

OWT在Docker中运行时,Docker就相当于一个局域网,OWT获取到地址是个内网IP,在外面是无法访问的,所以需要修改配置。

比如,我们在Docker中查看OWT的IP,可以发现是eth0 172.17.0.2

root@d3041e7dd80d:/tmp/git/owt-docker/owt-server-4.3# ifconfig eth0| grep inet
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255

我们在Host机器(也就是运行Docker的机器上)查看IP,可以发现是en0 192.168.1.4(以Mac为例):

Mac:owt-docker chengli.ycl$ ifconfig en0 inet|grep inet
	inet 192.168.1.4 netmask 0xffffff00 broadcast 192.168.1.255

那么我们就需要修改OWT的配置,让它知道自己应该对外使用192.168.1.4这个宿主机的地址(当然如果有公网IP也可以)。

  • dist/webrtc_agent/agent.toml,修改[webrtc]中的network_interfaces,是媒体流的服务地址。
  • dist/portal/portal.toml,修改[portal]中的ip_address,是信令的服务地址。

Docker提供了更好的办法,可以将宿主机的IP(192.168.1.4)通过--env传给OWT,通过读取环境变量获取IP:

HostIP=`ifconfig en0 inet| grep inet|awk '{print $2}'` &&
docker run -it --env DOCKER_HOST=$HostIP \
    registry.cn-hangzhou.aliyuncs.com/ossrs/owt:4.3 bash

Remark: 注意应该映射端口,这里为了强调域名就没有把端口映射写上。

这样在Docker中就可以知道宿主机的IP地址了(或者公网IP也可以):

root@d5a5bc41169e:/tmp/git/owt-docker/owt-server-4.3# echo $DOCKER_HOST
192.168.1.4

我们就可以将OWT对外暴露的服务,修改为环境变量$DOCKER_HOST,避免每次启动都要改配置:

# vi dist/webrtc_agent/agent.toml
[webrtc]
network_interfaces = [{name="eth0",replaced_ip_address="$DOCKER_HOST"}]  # default: []

# vi dist/portal/portal.toml
[portal]
ip_address = "$DOCKER_HOST" #default: ""

启动OWT时,会被替换成IP地址。

Remark: 注意我们在Docker中修改了OWT,提交了PR参考

当然,若有公网可以访问的域名,或者公网IP,直接修改为IP或域名也可以:

# vi dist/webrtc_agent/agent.toml
[webrtc]
network_interfaces = [{name="eth0",replaced_ip_address="192.168.1.4"}]  # default: []

# vi dist/portal/portal.toml
[portal]
ip_address = "192.168.1.4" #default: ""

Auth Update

若使用镜像registry.cn-hangzhou.aliyuncs.com/ossrs/owt:pack,没有修改UDP端口,也没有修改脚本,启动OWT时会提示:

Update RabbitMQ/MongoDB Account? [No/Yes]

会在10秒后默认选择No,我们修改了这个脚本dist/bin/init-all.sh

if ${HARDWARE}; then
  echo "Initializing with hardware msdk"
  init_hardware
  #init_auth
else
  echo "Initializing..."
  init_software
  #init_auth
fi

这样就默认不会更新MongoDB和RabbitMQ的认证信息,直接启动服务了。

Performance

MacPro信息:

  • macOS Mojave
  • Version 10.14.6 (18G3020)
  • MacBook Pro (Retina, 15-inch, Mid 2015)
  • Processor: 2.2 GHz Intel Core i7
  • Memory: 16 GB 1600 MHz DDR3

Docker信息:

  • Docker Desktop 2.2.0.3(42716)
  • Engine: 19.03.5
  • Resources: CPUs 4, Memory 4GB, Swap 1GB

下面是不同人数和模式的测试数据:

模式 参数 人数 CPU CPU
(webrtc)
CPU
(video)
CPU
(audio)
Memory Memory
(webrtc)
Memory
(video)
Memory
(audio)
Load
MCU 2 72% 28% 32% 12% 238MB 93MB 85MB 56MB 2.38
MCU 4 119% 44% 57% 18% 267MB 98MB 94MB 75MB 3.41
SFU forward=true 2 35% 35% 0% 0% 64MB 64MB 0MB 0MB 2.38
SFU forward=true 4 87% 87% 0% 0% 95MB 95MB 0MB 0MB 9.29
MCU forward=true 2 61% 39% 22% 0% 121MB 64MB 57MB 0MB 4.81
MCU forward=true 4 130% 91% 24% 14% 230MB 93MB 65MB 72MB 9.83

Note: 默认是MCU+SFU模式,SFU模式参考SFU Mode

Note: 删除Views是指在管理后台,例如 https://192.168.1.4:3300/console/ 的房间设置中,删除Views然后Apply。

Note: Intel的朋友反馈,在一台8核3.5GHZUbuntu机器(台式机)上,给Docker分配4核4GB内存,跑4个SFU,CPU占用率38%左右(WebRTC)。同样条件,4个MCU页面,CPU使用87%,其中WebRTC占用22%,MCU占用65%(视频46%、音频19%)。

下面是WebRTC这个Agent的性能指标:

模式 人数 CPU Memory Threads 线程增长
MCU 0 0% 47MB 36 -
MCU 1 11% 58MB 46 -
MCU 2 24% 62MB 55 19%
MCU 3 37% 67MB 64 16%
MCU 4 62% 72MB 73 14%

Note: 可以看到,由于直接使用了WebRTC,使用的线程数和人数正关联,限制了能支持的并发数目。由于WebRTC不涉及编解码运算,属于IO密集型,个人觉得这里有可以提升的空间。

下面是Video这个Agent的性能指标:

模式 人数 CPU Memory Threads 线程增长
MCU 0 0% 46MB 10 -
MCU 1 18% 66MB 20 -
MCU 2 22% 71MB 21 5%
MCU 3 33% 78MB 22 4%
MCU 4 74% 83MB 23 4%

下面是Audio这个Agent的性能指标:

模式 人数 CPU Memory Threads 线程增长
MCU 0 0.3% 43MB 10 -
MCU 1 4.7% 47MB 16 -
MCU 2 9.3% 53MB 20 25%
MCU 3 13% 63MB 24 20%
MCU 4 26% 73MB 28 16%

Note: Video和Audio都是编解码运算,是CPU密集型,线程随人数正向增长符合预期。

SFU Mode

OWT默认是MCU+SFU模式,比如打开两个页面:

其实上面的forward=true,并不是仅仅只有SFU模式,只是拉了转发的流。若需要关闭MCU模式,只开启SFU:

  1. 打开管理后台:https://192.168.1.4:3300/console
  2. 输入ServiceID和Key,在启动OWT服务时,会打印出来,比如:sampleServiceIdsampleServiceKey
  3. 进入后台后,可以看到Room,View Count默认是1,选择Detail,看到详细的房间配置。
  4. 在Room配置中,Views那一节,点按钮Remove,删除views配置,在页面最底下点对勾提交。
  5. Apply按钮应用房间配置,这时候可以看到View Count是0。

这样操作后,再打开页面就只有SFU模式了,不再有video和audio的进程消耗CPU:https://192.168.1.4:3004/?forward=true

Note: SFU模式下,可以停止掉video-agent和audio-agent,流直接通过webrtc-agent中转。

Note: MCU模式下,推流先到webrt-agent,video会新建TCP连接从webrtc-agent拉流。每个人的订阅,都会从webrtc-agent拉合屏的流,webrtc-agent从video新建个TCP连接拉流。

Notes

  • CodeNodejs 关于程序结构,调用关系,Nodejs和C++代码如何组合。
  • CodeVideo 关于MCU的video处理部分,如果获取原始视频流,合屏,转码。
    • Scripts 启动脚本,调试nodejs部分。
    • Heartbeat nodejs子进程和心跳消息。
    • Load Balancer nodejs子进程负载均衡。
    • Schedule 调度到video进程处理视频。
    • VideoNode video的处理流程,和webrtc-agent的通信,mixer和transcoder。
    • GDB Debug 如何使用GDB调试C++代码。
    • VideoMixer In mixer输入部分,从webrtc-agent读取数据,读取Frame,解码。
    • VideoMixer Out mixer输出部分,合流,编码,输出到webrtc-agent。

Note: VideoNode video的处理流程,和webrtc-agent的通信,mixer和transcoder。

Note: VideoMixer In mixer输入部分,从webrtc-agent读取数据,读取Frame,解码。

Note: VideoMixer Out mixer输出部分,合流,编码,输出到webrtc-agent。

Issues

  1. OWT UDP端口没有复用,导致需要开一系列端口,参考Port Range
  2. OWT对外的服务发现,也就是返回给客户端的信令和UDP的IP,是通过配置文件,参考Docker Host IP
  3. OWT的webrtc_agent,使用WebRTC收发流,线程数会随着用户数增多而增多,导致SFU模式下也不能有很高并发,参考Performance: webrtc-agent
  4. OWT实现了完整的集群,包括Node的负载管理和调度,服务发现和路由,而实际中比较复杂的业务系统会有自己的调度和服务管理,这导致OWT集成到现有系统比较复杂,参考OWT Schedule
  5. OWT选择的是多PC,MCU下就是2个PC,SFU下会有很多个PC。人数比较多时OWT的SFU工作不太好,不过可以选择MCU模式。
  6. OWT每个进程一个日志文件,日志没有业务逻辑区分,全链路排查问题时会比较困难,比如一个进程服务了30个人,一般有问题的是几个人,怎么把有问题的人的日志分离出来。
  7. OWT依赖nodejs,每次打包都会下载N多个依赖,而且是从网络上下载,有时候就是会一直失败。
  8. OWT每个模块都使用了进程间通信,比如webrtc和video之间走的是TCP,要求部署在一个机房,无法支持跨区域级联。
MIT License Copyright (c) 2020 winlin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

Mirror for https://github.com/winlinvip/owt-docker 展开 收起
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/winlinvip/owt-docker.git
git@gitee.com:winlinvip/owt-docker.git
winlinvip
owt-docker
owt-docker
master

搜索帮助

14c37bed 8189591 565d56ea 8189591