SRS的配置文件模块SrsConfig—SRS源码分析
作者:罗上文,微信:Loken1,公众号:FFmpeg弦外之音
SrsConfig 不只是解析配置文件,同时负责解析命令行的参数。解析命令行参数的函数是 parse_options()
与 parse_argv()
,如下:
命令行参数的解析逻辑比较简单,这里就不说了,跳过。值得注意的是上图中的 _argv
变量,他存储了整个命令行的字符串。但是也没有太多的用处,就是简单保存一下命令行字符串。
下面我们开始讲解 SrsConfig
里解析配置文件的逻辑,我们先看一下 conf/clion.conf
文件的格式,如下:
listen 1935;
max_connections 1000;
daemon on;
srs_log_level info;
srs_log_tank console;
http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
}
http_api {
enabled on;
listen 8080;
}
stats {
network 0;
}
rtc_server {
enabled on;
# Listen at udp://8000
listen 8000;
#
# The $CANDIDATE means fetch from env, if not configed, use * as default.
#
# The * means retrieving server IP automatically, from all network interfaces,
# @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#config-candidate
candidate $CANDIDATE;
}
...省略...
SRS 解析配置文件的函数是 SrsConfig::parse_file()
,他会先把 srs.conf
配置文件的内容全部读取进去 SrsConfigBuffer
,然后再解析 SrsConfigBuffer
流程如下:
build_buffer()
会把整个 srs.conf
文件的内容读取进去 SrsConfigBuffer
里面。然后 parse_buffer()
负责把 SrsConfigBuffer
解析成 SrsConfDirective
的树结构。
SrsConfDirective
树结构是一个重点,他的代码注释非常全,如下:
你看一遍他的代码注释,然后自己断点调试一下,就知道是解析处理之后的结果是怎样的了。
然后 SrsConfig
还提供了一些方法来获取 SrsConfDirective
树里面的某些项的信息,例如 get_pid_file()
,如下:
而 get()
函数实际上是去遍历整个 SrsConfDirective
树,如下:
解析 srs.conf
配置文件的代码还是比较简单的,稍微比较复杂的是 配置文件的 reload 功能。reload 功能是通过 subscribes
机制来实现的,如下:
注意这个 subscribes
字段,他是一个 vector
(订阅者数组)。我习惯将 vector
称为数组。虽然不太准确,但你知道这么个意思就行了。
其他模块如果 需要响应配置文件的 reload 事件,可以用 subscribe()
函数把自己(this)注册进去 vector
数组。如下:
上图是 RTMP 模块,订阅了 SrsConfig
的 reload
。当配置文件被热加载的时候,SrsConfig
就会执行 RTMP 模块里跟 reload
相关的函数,如下:
流程图如下:
注意 SrsConfig
里面的动作方法是 do_
开头的,而订阅者里面的方法是 on_
开头的,这是 SRS 的命名习惯。
信号产生之后,就会执行相关的 do
方法,do
方法里面会遍历所有的订阅者,执行他们的 on
方法。例如 do_reload_listen()
里面会遍历所有的订阅者,执行他们的 on_reload_listen()
函数,如下:
我们可以用下面的命令来产生 SRS_SIGNAL_RELOAD
信号给 SRS 进程,如下:
./etc/init.d/srs reload
SRS 的信号处理也是一个比较有趣的设计,他会把信号事件 传递给 pipe 管道,因为 pipe 是 IO 操作,所以就可以用协程来处理了。推荐阅读《SRS的信号处理模块SrsSignalManager》
虽然 SRS 官方文档《热加载配置》说支持除 deamon
,mode
以外的配置选项进行热加载,但是我测试下来还是有一些配置是不支持热加载的,例如 srs_log_level
。