Written by 马鹏飞, Winlin
什么才是更好的配置方法?NGINX的conf,还是MySQL的ini,还是新潮的yaml,或者JS友好的json?它们都有各自的问题,最好的方式是conf 环境变量,也就是Grafana的配置方法。
Why Important?
为何配置这么重要?因为它是最基本的API,也就是程序和人的接口,也决定了使用体验是否良好。想象下xml的配置文件,想起来都觉得烦躁,这是因为xml并不是对人友好的接口。
SRS的配置一直都对人挺友好的,因为是使用的NGINX的配置方法,熟悉NGINX的同学可能会觉得很熟悉,比如:
代码语言:javascript复制listen 1935;
max_connections 1000;
vhost __defaultVhost__ {
}
相当直观和好理解,这些年也就这么过来了,但它并非没有问题,比如:
- • 程序读写不友好,要用代码修改配置,就需要自己实现这个解析。NGINX是有生态支撑,有工具支持读写,但它只支持NGINX的配置,并不是所有conf格式都能支持。
- • 在文档或Wiki中,或者在给出例子时,总是要给出一个配置文件,而一般还需要修改现有的配置文件,很不方便,也有可能会出错。
- • 在K8s部署时,或者Docker启动时,需要创建文件,并映射到Docker中,哪怕只需要修改某个配置项,也需要这么做,这套机制很麻烦。
也正是因为有这些问题,陆陆续续的有同学提出来支持其他的配置方式,详细可以参考#2277[1]中的详细讨论,大概有几种解决方案:
- • 支持JSON或YAML,这是为了解决程序读写的问题,JSON对JS程序员友好,YAML对DevOps友好。无论哪种方式,都不能对所有人友好,而且还解决不了后面两个问题,还是依赖文件。
- • 支持Redis那种命令行参数的方式,这解决了配置文件的问题,对人也相对比较友好,但若有参数变更,则还是需要依赖文件。
- • 环境变量,方便设置和命令行启动,是基本的传递配置的办法,但多了后不太友好,另外和目前的文件配置方法有差异,导致Reload等机制需要修改。
Note: 如果直接换成新的配置方式,都会对目前支持的NGINX的conf文件的方式造成不兼容,影响使用习惯。因此最好的办法不是替代,而是结合现有配置方法,实现配置能力的增强。
直到看到了Grafana的配置方式,发现了在目前基础上,可以更好的配置方法。
Solution
目前NGINX的conf的配置方法,是对人比较友好的,需要支持的是对程序接口友好的方式,而且是和这种方式是可以配合而不是替代的方案。这就是环境变量的方式,先看Grafana的启动方式:
代码语言:javascript复制docker run --rm -it --name grafana
--env GF_SECURITY_ADMIN_USER=admin
--env GF_SECURITY_ADMIN_PASSWORD=admin
--env GF_DATABASE_TYPE=mysql
--env GF_DATABASE_HOST=host.docker.internal:3306
--env GF_DATABASE_NAME=grafana
--env GF_DATABASE_USER=root
--env GF_DATABASE_PASSWORD=******
--env GF_INSTALL_PLUGINS=tencentcloud-monitor-app
-p 3000:3000
grafana/grafana
这种方式是最方便用Docker启动的方式,在K8s中也是一样的。Grafana所有的配置既可以通过配置文件配置,也可以通过环境变量配置。
借鉴这种办法,SRS的配置也可以支持环境变量,比如WebRTC over TCP[2]:
代码语言:javascript复制docker run --rm -it -p 8080:8080 -p 1985:1985 -p 8000:8000
-e CANDIDATE="192.168.3.82"
-e SRS_RTC_SERVER_TCP_ENABLED=on
-e SRS_RTC_SERVER_PROTOCOL=tcp
registry.cn-hangzhou.aliyuncs.com/ossrs/srs:v5.0.60
无论是命令行启动,还是Docker启动,还是分享命令给其他人,还是K8s启动,这都是最简单直接的办法。
Note: 一般我们并不会需要修改特别多的配置,往往只需要修改几个配置,因此这种方式是最便捷的。
当然也不是所有SRS的配置都支持环境变量,因为有些配置比如Transcode是数组,就很难支持,具体以full.conf[3]中标记为Overwrite by env SRS_XXX
为准,比如:
# Overwrite by env SRS_LISTEN
listen 1935;
# Overwrite by env SRS_MAX_CONNECTIONS
max_connections 1000;
rtc_server {
# Overwrite by env SRS_RTC_SERVER_ENABLED
enabled on;
}
vhost __defaultVhost__ {
rtc {
# Overwrite by env SRS_VHOST_RTC_ENABLED for all vhosts.
enabled on;
}
}
基本上SRS的配置都支持了环境变量的覆盖,非常感谢mapengfei53[4]的贡献。
Next
目前SRS支持了环境变量的配置,还需要改进支持Reload。
由于Reload依赖配置文件,在收到Reload信号后,重新加载配置文件,对比发现变更后,实现定向的快速Reload。而环境变量的配置,则需要实现对应的变更检测机制,我们会在后续改进和完善。
此外,之前Reload的机制过度设计,有些其实没有必要支持Reload,比如侦听的端口,是不会在运行中变化,而且变化会导致很多异常问题。因此,会在未来把很多不常用的Reload功能去掉,只支持必要的Reload。
还有,K8s中的配置是通过ConfigMap加载到容器,而通过inotify机制,可以在文件内容修改后,主动加载配置Reload,而不需要发送Reload信号,这样在K8s集群中只需要修改ConfigMap就会自动生效到容器。这个机制同样也需要支持环境变量,如何在环境变量变更后,在K8s集群中生效。
最后补充一句:SRS会永远支持配置文件,以及对应的配置变更Reload机制,环境变量的配置方法,是对目前配置能力的完善,并不是替代。
引用链接
[1]
#2277: https://github.com/ossrs/srs/issues/2277
[2]
WebRTC over TCP: https://ossrs.net/lts/zh-cn/docs/v5/doc/webrtc#webrtc-over-tcp
[3]
full.conf: https://github.com/ossrs/srs/blob/develop/trunk/conf/full.conf
[4]
mapengfei53: https://github.com/mapengfei53