信令服务进程启动worker进程
1.官方demo提供的启动方式
官方提供的mediasoup-demo是由js(信令)+c++(流媒体服务)两部分服务,mediasoup的worker进程是nodejs通过child_process 的spawn()接口启动的
打开server.js 文件
go
server.js文件
async function run()
{
// Open the interactive server.
await interactiveServer();
// Open the interactive client.
if (process.env.INTERACTIVE === 'true' || process.env.INTERACTIVE === '1')
await interactiveClient();
// Run a mediasoup Worker.
await runMediasoupWorkers(); //内部会创建worker
// Create Express app.
await createExpressApp();
// Run HTTPS server.
await runHttpsServer();
// Run a protoo WebSocketServer.
await runProtooWebSocketServer();
// Log rooms status every X seconds.
setInterval(() =>
{
for (const room of rooms.values())
{
room.logStatus();
}
}, 120000);
}
runMediasoupWorkers()函数,首先获得当前机器cpu核数,有几核就创建几个woker
go
// Number of mediasoup workers to launch.
numWorkers : Object.keys(os.cpus()).length,
创建woker的函数
go
async function runMediasoupWorkers()
{
const { numWorkers } = config.mediasoup;
logger.info('running %d mediasoup Workers...', numWorkers);
for (let i = 0; i < numWorkers; ++i)
{
const worker = await mediasoup.createWorker(
{
logLevel : config.mediasoup.workerSettings.logLevel,
logTags : config.mediasoup.workerSettings.logTags,
rtcMinPort : Number(config.mediasoup.workerSettings.rtcMinPort),
rtcMaxPort : Number(config.mediasoup.workerSettings.rtcMaxPort)
});
.....
.....
}
最终代码会调用到 mediasoup-demo/server/node_modules/mediasoup/src/index.ts中的createWorker()函数
go
export async function createWorker(
......
......
const worker = new Worker(
{
logLevel,
logTags,
rtcMinPort,
rtcMaxPort,
dtlsCertificateFile,
dtlsPrivateKeyFile,
appData
});
.....
)
代码调用到 mediasoup-demo/server/node_modules/mediasoup/src/Worker.ts文件
node.js 通过spawn启动mediasoup-worker进程,spawn学习:https://www.runoob.com/nodejs/nodejs-process.html
go
Woker的构造函数
this._child = spawn(
// command
spawnBin,
// args
spawnArgs,
// options
//同时创建用于通信的管道
this._channel = new Channel(
{
producerSocket : this._child.stdio[3],
consumerSocket : this._child.stdio[4],
pid : this._pid
});
producerSocket stdio[3] 用来发送数据给子进程,consumerSocket stdio[4] 用来接收数据
如果给worker发送消息,详情见Channel.ts
// This may throw if closed or remote side ended.
this._producerSocket.write(ns);
同时也创建了PayloadChannel
this._payloadChannel = new PayloadChannel(
{
// NOTE: TypeScript does not like more than 5 fds.
// @ts-ignore
producerSocket : this._child.stdio[5],
// @ts-ignore
consumerSocket : this._child.stdio[6]
});
mediasoup是根据当前机器cpu核数,选择创建几个worker进程
跳转到mediasoup-demo/server/node_modules/mediasoup/src/index.ts
在跳转到mediasoup-demo/server/node_modules/mediasoup/src/Worker.ts
2.自行启动mediasoup
如果读者仅仅是需要学习mediasoup c++部分,则可以编辑脚本启动mediasoup服务
参考:
vim config.ini
bash
[General]
servercount = 2
[Server0]
id = 1
udpport = 52000
ip = 127.0.0.1
vrvmeetingport = 8108
[Server1]
id = 2
udpport = 53000
ip = 127.0.0.1
vrvmeetingport = 8108
vim start.sh
bash
#!/bin/bash
ulimit -c unlimited
configFile="./config.ini"
function ReadINIfile()
{
Key=$1
Section=$2
Configfile=$3
ReadINI=`awk -F '=' '/\['$Section'\]/{a=1}a==1&&$1~/'$Key'/{print $2;exit}' $Configfile`
echo "$ReadINI"
}
serverCount=`ReadINIfile "servercount" "General" "$configFile"`
for((i=0; i<serverCount; i++))
do
Section="Server""$i"
id=`ReadINIfile "id" "$Section" "$configFile" | sed -e 's/^[ \t]*//g'`
udpPort=`ReadINIfile "udpport" "$Section" "$configFile" | sed -e 's/^[ \t]*//g'`
vrvmeetingIp=`ReadINIfile "vrvmeetingip" "$Section" "$configFile" | sed -e 's/^[ \t]*//g'`
vrvmeetingPort=`ReadINIfile "vrvmeetingport" "$Section" "$configFile" | sed -e 's/^[ \t]*//g'`
iperfPort=`ReadINIfile "iperfport" "$Section" "$configFile" | sed -e 's/^[ \t]*//g'`
nohup ./rtcMediaServer $id $vrvmeetingIp $vrvmeetingPort $iperfPort --logLevel=debug --logTag=info --logTag=ice --logTag=dtls --logTag=rtp --logTag=srtp --logTag=rtcp --logTag=rbe --logTag=rtx --rtcIPv4=true --rtcIPv6=false --singlePort=true --getkeyframe=5000 --rtcMinPort=$udpPort --rtcMaxPort=65535 & echo $! >> pid
done
执行sh start.sh
至此,mediasoup的worker进程已经成功启动
随后梳理mediasoup中的worker创建