Streaming服务的布署和维护
安装包和许可文件
流媒体服务交付时,将提供一个安装包文件和一个许可文件。
安装包文件为streaming-release-x.x.x.zip
(其中x.x.x
为版本号)压缩包文件。压缩包内包含以下文件:
文件名 | 说明 |
---|---|
config/application.yml | 配置文件1 |
config/config.json | 配置文件2 |
config/trusted-clients.json | 信任客户端表数据文件 |
config/log4j.xml | 程序日志配置文件 |
start.sh | 程序启动脚本文件 |
streaming.service | Streaming 服务的systemd 服务单元文件 |
streaming-x.x.x.jar | 流媒体服务Jar包(其中x.x.x 为版本号) |
许可文件为streaming-cert.json
,此文件另行交付。
程序的安装
本文假设:
- 操作系统为
Ubuntu Server 20.04
,并已经完成一般性操作系统环境的准备 - 域名为:
wx.gratour.info
,按下文配置时,应改为实际的域名 - 操作系统用户名为:
streaming
,按下文配置时,应改为实际的用户名 - Java使用JDK版本,安装在
/opt/jdk-21
程序端口规划
Streaming
服务需要在以下端口监听(均为TCP协议),部分只在本机内内部使用,部分需要开放内网访问,部分需要开放外网访问。
对于需要外网访问的端口,本文假设外网端口和内网端口一致。
端口号 | 内网入站访问需求 | 外网入站访问需求 | 用途 |
---|---|---|---|
1975 | Y | 终端JT/T 808协议接入端口 | |
2000 | Y | Y | 流媒体服务API接口端口(https) |
2001 | Y | Y | 媒体发布端口(FLV-HTTPS) |
2002 | Y | Y | 媒体发布端口(FLV-HTTP, 实时) |
2003 | Y | Y | 媒体发布端口(FLV-HTTP, 回放) |
2004 | Y | Y | 媒体发布端口(WSS) |
2005 | Y | Y | 新版WebsocketAPI端口 |
2006 | Y | 终端JT/T 1078 接收端口 | |
2007 | Y | 终端JT/T 1078 接收端口 | |
2008 | Y | 终端JT/T 1078 接收端口 | |
2009 | Y | 终端ADAS附件接收端口 | |
2010 | Y | FTP信令端口 | |
2011-2030 | Y | FTP数据端口(passive模式),应设置20个端口号或以上,内外网端口号必须一致 |
目录规划
/opt/strm-fs
目录:用于Streaming
服务和Micro-GNSS
服务存储服务端音视频转储文件、附件等文件/opt/strm
目录:用于安装Streaming
服务/opt/certs
目录:用于存放域名的SSL证书文件,此目录应可为服务执行用户(本文假设为streaming
)读取
创建这两个目录并将目录属主改为规划的运行用户(本文假设为streaming
):
sudo mkdir /opt/strm
sudo chown streaming:streaming /opt/strm
sudo mkdir /opt/strm-fs
sudo chown streaming:streaming /opt/strm-fs
安装 ZooKeeper 服务程序
从 https://zookeeper.apache.org/ 网站下载安装文件并安装,设置好服务端口号(此端口仅内部使用).
安装 Streaming 服务程序
- 解压压缩包文件到
/opt/streaming
目录:
unzip streaming-release-x.x.x.zip -d /opt/strm
- 修改
/opt/strm/start.sh
文件中的JAVA_HOME
变量的赋值(下图第一个黄色荧光部分) ,使之符合实际Java的安装路径(此处安装的是JDK版),并将最后一行的命令行的jar文件路径改为实际的文件路径( 下图第二个黄色荧光部分):
#!/bin/bash
export JAVA_HOME=/opt/jdk-21
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
java -Djava.net.preferIPv4Stack=true -Duser.timezone=Asia/Shanghai -jar /opt/strm/streaming-4.0.10.jar
- 为
/opt/strm/start.sh
添加可执行属性:
chmod +x start.sh
- 修改
/opt/strm/streaming.service
文件中的WorkingDirectory
属性,使之符合Streaming
服务实际的安装目录; 修改User
属性为执行服务的用户的用户名;修改ExecStart
属性中的黄色荧光部分,改为start.sh
文件的实际路径:
[Unit]
Description=GT Streaming Service
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
WorkingDirectory=/opt/strm
Restart=always
RestartSec=5
User=streaming
ExecStart=/bin/bash /opt/strm/start.sh
[Install]
WantedBy=multi-user.target
- 将
/opt/strm/streaming.service
复制到/etc/systemd/system
目录下,并激活(enable
)服务(但先不要启动,因为后面还有一些配置要完成):
sudo cp /opt/strm/streaming.service /etc/systemd/system/
sudo systemctl enable streaming
- 将域名的SSL证书文件复制到某个
streaming
用户可读取的目录,这里假设为/opt/certs
目录 - 修改
/opt/strm/config/application.yml
文件:- 修改
server.port
属性的值为流媒体服务API接口端口的端口号;HTTPS 协议。 - 修改
server.private-port
属性的值为内部接口端口的端口号; 默认 HTTPS 协议,设置server.ssl.private-port-plain-http
为true
可以调整为 HTTP 协议。 - 修改
server.ssl.certificate
属性的值设为域名SSL证书文件(PEM格式)的文件路径; - 修改
server.ssl.certificate-private-key
属性的值设为域名SSL 私钥文件(PEM格式)的文件路径;
- 修改
server:
port: 2000
private-port: 2001
ssl:
certificate: "/opt/certs/wx.gratour.info-certificate.pem"
certificate-private-key: "/opt/certs/wx.gratour.info-private-key.pem"
private-port-plain-http: true
enabled: true
- 将许可文件
streaming-cert.json
文件复制到/opt/strm/config
目录下(不要修改此文件的内容) - 根据下表说明,按实际情况和/或需要修改
/opt/strm/config/config.json
文件:
文件的初始内容大致如下:
{
"instIdPrefix": "strm",
"db": {
"jdbcUrl": "jdbc:postgresql://localhost:5432/strm",
"user": "strm",
"pwd": "strm",
"strmLogCleanupCron": "0 0 1 * * *",
"strmStatCron": "0 40 1 * * *"
},
"externalAddr": "wx.gratour.info",
"mq": {
"kafka": {
"servers": "192.168.80.106:9092,192.168.80.107:9092,192.168.80.108:9092",
"groupId": "strm"
},
"redis": {
"host": "192.168.80.106",
"port": 6379,
"database": 1
},
"adaptor": {
"script": "e-eye",
"logEnabled": true
},
"termCmd": {
"channel": "redis",
"destination": "gnss_cmd:gateway:send",
"useAdaptor": true
},
"cmdStateChanged": {
"channel": "kafka",
"destination": "inet-cmd-ack",
"useAdaptor": true
}
},
"zk": {
"connectString": "192.168.1.129:2181"
},
"endPoint": {
"ports": {
"livePort": 2006,
"replayPort": 2007,
"talkPort": 2008
}
},
"gnss": {
"jt808Host": "wx.gratour.info",
"jt808Ports": [
7510
],
"spiVersion": "1.0.0",
"features": {
"batchOnlineTermsQryDisabled": true,
"attrsQry": false,
"avAttrsQry": false,
"noQryLocationCmd": true,
"exposeJt808Addr": true
}
},
"publisher": {
"livePort": 2001,
"liveHttpPort": 2002,
"replayHttpPort": 2003,
"websocketPort": 2004,
"ws2Port": 2005,
"hls": {
"tmpDir": "/opt/strm-fs/hls"
}
},
"ftp": {
"port": 2010,
"passivePorts": "2011-2030",
"storePath": "/opt/strm-fs/ftp"
},
"avDump": {
"storePath": "/opt/strm-fs/strm",
"cleanup": {
"enabled": true,
"cron": "0 0 2 * * *",
"keepDays": 7
}
},
"adas": {
"cleanup": {
"enabled": true,
"cron": "0 0 0/2 * * ?",
"keepDays": 190
},
"port": 2009
},
"options": {}
}
文件中的各属性说明如下:
属性名 | 数据类型 | 修改说明 |
---|---|---|
instIdPrefix | 字符串 | 实例ID前缀;可分配任意要可见ASCII字符;如果整个系统中(即使不在同一台机器上)有多个Streaming 服务实例,则应分配不同的ID前缀给每个实例 |
db.jdbcUrl | 字符串 | 数据库的JDBC URL |
db.user | 字符串 | 数据库用户名 |
db.pwd | 字符串 | 数据库密码 |
db.strmLogCleanupCron | 字符串 | 执行流媒体日志记录自动清理的 Spring CRON 调度时间表达式,服务将依照此表达式定义的时间执行周期性的日志记录清理工作 |
db.codeStrmLogCleanupCron | 字符串 | 执行流媒体码流日志记录自动清理的 Spring CRON 调度时间表达式,服务将依照此表达式定义的时间执行周期性的日志记录清理工作 |
db.strmStatCron | 字符串 | 执行流媒体活动统计的 Spring CRON 调度时间表达式,服务将依照此表达式定义的时间执行周期性的隔日统计工作 |
externalAddr | 字符串 | 外部地址,应填写服务器的域名 |
mq.kafka.servers | 字符串 | Kafka集群地址 |
mq.kafka.groupId | 字符串 | Kafka的Group ID |
mq.redis.host | 字符串 | Redis主机地址 |
mq.redis.port | 整数 | Redis服务端口号 |
mq.redis.database | 整数 | Redis的数据库号 |
mq.adaptor.script | 字符串 | 消息转换脚本的名称,消息转换脚本存放在 config/script 目录下,此属性设置文件名(不带扩展名,扩展名必须为.mjs ),如设置为 e-eye ,则脚本文件为 config/script/e-eye.mjs |
mq.adaptor.logEnabled | 布尔值 | 是否输出脚本中的日志输出信息到日志 |
mq.termCmd.channel | 字符串 | 媒体服务下发指令使用的通道(消息队列),为 rabbit , kafka , redis 之一 |
mq.termCmd.destination | 字符串 | 消息队列的topic或destination |
mq.termCmd.useAdaptor | 布尔值 | 是否调用消息转换脚本(见mq.adaptor.script )的特定方法将指令(TermCmd 对象)转换成集成系统所需要的格式再发到消息队列 |
mq.cmdStateChange.channel | 字符串 | 媒体服务接收指令状态变更使用的通道(消息队列),为 rabbit , kafka , redis 之一 |
mq.cmdStateChange.destination | 字符串 | 消息队列的topic或destination |
mq.cmdStateChange.useAdaptor | 布尔值 | 是否调用消息转换脚本(见mq.adaptor.script )的特定方法将从消息队列接收到消息转换成 TermCmdStateChanged 信息对象 |
zk.connectString | 字符串 | ZooKeeper服务的地址 |
endPoint.ports.livePort | 整数 | JT/T 1078协议终端实时码流接收端口;此端口要求外网访问 |
endPoint.ports.replayPort | 整数 | JT/T 1078协议终端回放码流接收端口此端口要求外网访问 |
endPoint.ports.talkPort | 整数 | JT/T 1078协议终端对讲码流接收端口;此端口要求外网访问 |
publisher.livePort | 整数 | FLV-HTTPS实时播放端口;此端口要求外网访问,否则只能内网播放 |
publisher.liveHttpPort | 整数 | FLV-HTTP实时播放端口;此端口要求外网访问,否则只能内网播放 |
publisher.replayHttpPort | 整数 | FLV-HTTP回放播放端口;此端口要求外网访问,否则只能内网播放 |
publisher.websocketPort | 整数 | FLV-Websocket端口;此端口要求外网访问,否则只能内网播放 |
publisher.ws2Port | 整数 | 新版WebSocket API服务端口 |
publisher.hls.tmpDir | 字符串 | 音视频HLS转码的临时文件存储目录;可设置到/opt/strm-fs 的hls 子目录,或/tmp/hls ,必须为服务执行用户可读写的目录;目录不存在时,服务将在启动时创建此目录 |
avDump.storePath | 字符串 | 服务端音视频转储文件存储目录;一般为/opt/strm-fs 的strm 子目录,必须为服务执行用户可读写的目录;目录不存在时,服务将在启动时创建此目录 |
avDump.cleanup.enabled | 布尔值 | 是否执行服务端音视频转储文件自动清理;一般应设为true |
avDump.cleanup.cron | 字符串 | 服务端音视频转储文件自动清理 Spring CRON 调度时间表达式;请务必将自动清理工作安排在每天凌晨2点之后,在0点至2点之间执行统计可能导致统计不准确;服务将依照此表达式定义的时间执行周期性的音视频转储文件清理工作 |
avDump.cleanup.keepDays | 整数 | 执行服务端音视频转储文件自动清理时,保留的最近转储文件的天数;转储时间在此天数内的文件不会被清理掉;应大于0。默认为32天 |
ftp.port | 整数 | FTP(用于接收终端远程录像上传)的信令端口 |
ftp.passivePorts | 字符串 | FTP数据端口(passive模式),应设置20个端口号或以上,内外网端口号必须一致。支持设置多个端口,可用逗号分隔单个端口或端口范围,端口范围用 - 号连起来 |
ftp.storePath | 字符串 | 用于存储FTP接收到的文件的目录 |
adas.port | 整数 | 主动安全附件服务接收文件的端口 |
adas.cleanup.enabled | 布尔值 | 是否执行主动安全附件文件的自动清理;一般应设为true |
adas.cleanup.cron | 字符串 | 主动安全附件文件自动清理 Spring CRON 调度时间表达式;服务将依照此表达式定义的时间执行周期性的主动安全附件文件清理工作 |
adas.cleanup.keepDays | 整数 | 执行主动安全附件文件自动清理时,保留的最近上传的主动安全附件文件的天数;上传时间在此天数内的文件不会被清理掉;应大于0。默认为190天 |
- 将
/opt/strm/config/trusted-client.json
文件中的clients[0].password
属性的值修改为一个随机密码(不要使用文件中已有密码),建议生成长度为12个或以上的字母数字字符组成的密码。Micro-Gateway
服务将使用此密码访问安全敏感的接口。
{
"clients": [
{
"username": "gnss-1",
"password": "Jc4xrpsIX2c2PGSm",
"privs": [
"config", "strm"
]
}
]
}
根据前述端口需求,设置好防火墙和端口映射
启动服务
sudo systemctl start streaming
日常维护
服务的启动、停止、重启
- 启动
Streaming
服务可执行:
sudo systemctl start streaming
- 停止
Streaming
服务可执行:
sudo systemctl stop streaming
- 重启
Streaming
服务可执行:
sudo systemctl restart streaming
SSL证书更换
将PEM的格式证书(nginx格式)上传到配置的证书目录即可
日志文件
日志文件为服务安装目录(本文为opt/strm
)下的log
子目录下的strm.log
文件。
Spring CRON 调度时间表达式
Spring CRON
表达式类似于crontab表达式,但分为6个(crontab为5个,少了秒字段)以空格分隔的时间日期字段:
主要规则如下
- 字段可以设为星号(
*
),表示从第一个到最后一个。对于日
或周几
字段,可以用问号(?
),表示的意义和星号(*
)一样。 - 范围可以用连接号(
-
)连接两个数字表示;它表示的范围是包含的,即包含开始的数字,也包含结尾的数字;如:3-7
,表示[3
,4
,5
,6
,7
],范围包含开始数字3
,也包含结尾数字7
。 - 在一个字段中,单个数字或一个范围或星号(
*
)后跟/n
(其中n为具体数字),可表示在触发后,在范围内再多次触发,间隔由n
值指出。 - 在
日
字段中可以使用一个L
字符,表示月的最后一天。如果L
后面跟随一个负的偏量,即L-n
(其中n为具体数字),表示月的倒数n天。如果L
后面跟随W
字母,即LW
,则表示月的最后一个工作日。 - 在
周几
字段中可以使用一个L
字符,表示周的最后一天。如果在L
前面加一个数字,表示月的最后一个周几。 日
字段可以是nW
(其中n为具体数字),表示与n
号最接近的工作日;如果当月n
号刚好为工作日,则计算为n
号;如果n
不为1,n
号那天为周六,则计算为n
号的前一天(周五);如果n
为1,1
号那天为周六,则计算为1
号的下周一;如果n
号那天为周日,则为n
号的后一天(周一)。周几
字段可以指定为d#n
(其中d, n为具体数字),表示月的第n个周d。
同时也支持以下宏:
@yearly
(或@annually
),表示每年1月1日零时@monthly
,表示每月1日零时@weekly
,表示每个周日的零时@daily
(或@midnight
),表示每天的零时@hourly
,表示每个小时的0分0秒
表达式示例
表达式 | 说明 |
---|---|
0 0 * * * * | 每小时的0分0秒 |
*/10 * * * * * | 每隔10秒 |
0 0 8-10 * * * | 每天8点,9点,10点三个时刻 |
0 0 6,19 * * * | 每天的6点和19点二个时刻 |
0 0/30 8-10 * * * | 每天的8:00, 8:30, 9:00, 9:30, 10:00和10:30 |
0 0 9-17 * * 1-5 | 工作日的9点至17点的九个整点时刻 |
0 0 0 25 12 ? | 每年12月25日零时 |
0 0 0 L * * | 每个月的月末那天零时 |
0 0 0 L-3 * * | 每个月的倒数第三天的零时 |
0 0 0 1W * * | 每个月的第一个工作日的零时 |
0 0 0 LW * * | 每个月的最后一个工作日的零时 |
0 0 0 * * 5L | 每月最后一个周五的零时 |
0 0 0 ? * 5#2 | 每月第二个周五的零时 |