最近更新:2017.04.27 pm, by very80
需求
- 文件上传到OSS并转码完成后,由程序及时将预览文件传送到 192.168.10.55,供本地审核使用;
- 在备份服务器上,定时下载审核通过(启用)的素材源文件;
流程
- 客户上传视频,阿里云转码完成后,在回调处理中,将素材相关信息通过内部接口存入数据库表 oss_syncqueue;
也可以通过调用 api.xxx.com 的接口进行保存;
[请求方式]:POST
[POST数据]:
"programid"=>2, // ss_program 表的id
"tasktype"=>2, // 1=源文件,2=素材文件
"bucket"=>'xxx-data-upload', // OSS-bucket 名称
"name"=>'2017-04-24/7281280473e073f.mov', // Object name,相当于文件名,从oss-sdk 接口中获取到的数据
"url"=>'http://xxx-data-upload.oss-cn-shanghai.aliyuncs.com/2017-04-14/7281280473e073f.mov', // OSS url,从oss-sdk 接口中获取到的数据
"etag"=>'"F93CD36C35A60D8-49"', // etag,从oss-sdk 接口中获取到的数据
"lastmodified"=>'2017-04-14T10:02:09.000Z', // 上次更新时间,从oss-sdk 接口中获取到的数据
"type"=>'Multipart', // 文件类型,从oss-sdk 接口中获取到的数据
"size"=>156264049, // 文件大小,从oss-sdk 接口中获取到的数据
[返回结果]:json 文本串 :{"queueid":24} // 插入到数据库表 oss_syncqueue 后,新任务的id
- OSS同步任务创建接口收到请求后,插入到数据库表 oss_syncqueue,表结构见 附录一;
- api.xx.com 提供队列查询接口 getSyncTask,根据请求参数,返回若干队列任务;
- 192.168.10.55 和 源文件备份服务器上的nodeJS进程轮询 getSyncTask 接口, 按时间顺序获取最早的且状态为1的任务,每10秒查询一次;
- 查询到新任务时,根据任务表中的数据,调用 ali-oss sdk 的 signatureUrl(bucket, object) 接口,生成签名url;
- 在本机安装 aria2,并配置提供 jsonrpc 服务;
- nodeJS请求本机 aria2c 的 jsonrpc 接口,加入其下载任务队列,将自动开始下载,代码示例见 附录三;
- 在上一步中,添加下载任务时,设置 --on-download-complete 参数,以在aria2下载完成后,调用命令行执行以下操作:
7.1 更改db中的任务状态
7.1.1 aria2c.conf 中的相关配置:
on-download-complete=E:\web\vjhero\trunk\tools\oss_sync\code\download_complete.bat
on-download-error=E:\web\vjhero\trunk\tools\oss_sync\code\download_error.bat
7.1.2 .bat 脚本
# download_complete.bat
@echo off
node E:\web\vjhero\trunk\tools\oss_sync\code\index.js op=common/ossSyncComplete env=test.local filename="%3"
# download_error.bat
@echo off
node E:\web\vjhero\trunk\tools\oss_sync\code\index.js op=common/ossSyncError env=test.local filename="%3"
//
#download_complete.sh
#!/bin/sh
node /app/bin/vjnode/index.js op=common/ossSyncComplete env=10 filename="$3"
#download_complete.sh
#!/bin/sh
node /app/bin/vjnode/index.js op=common/ossSyncError env=10 filename="$3"
7.2 视频提取关键帧,计算特征码,入库,检查重复,并将检查结果通过远程接口调用存入数据库;
部署
运行环境
1.1 源文件下载:运行于windows系统,添加系统计划任务,每天0点5分开始运行,超过8点则程序退出,但之前已加入的下载会持续直到最终完成;
1.2 素材文件下载:运行于192.168.10.55(win2008r2),任务队列中的下载任务实时执行本地文件存储策略
2.1 从OSS上的文件名中解析出目录名,形如 2017-04-20/203a25bb.mp4, 建立目录,并保存文件
2.2 如果磁盘空间不足,采取线下手动处理服务器上安装 nodeJS 运行环境
3.1 nodeJS版本:V6.10.2
3.2 确保安装依赖模块:npm install co ali-oss websocket node-mysql
直接从代码库里拉取,则 node_modules 中已包含以上模块,无需再次安装
3.3 参数配置:在代码目录,%pathto%/inc/conf/conf.*.js 中,修改数据库连接、本地存储目录、aria2的rpc参数等;
'oss_sync':{
'save_to_dir':'D:\\files\\',
'download_server':{
'ADDRESS':'ws://127.0.0.1:6800/jsonrpc',
'METHOD': 'aria2.addUri',
'AUTH_TOKEN':'token:xxxdownloader'
},
'db_task_type':'THUMB',
'period':[0, 800] // true: 不限制时间
}
3.4 运行脚本,其中 env 参数用于区别加载不同环境的配置参数,包括下载目录、数据库连接等参数
node c:\vjtools\oss_sync\app\index.js env=55
// 在0.136 上
node /app/vjnode/index.js op=queue/handle env=ONLINE &
- 解压 aria2 程序压缩包到任意目录
4.1 aria2.conf 重要配置参数
max-concurrent-downloads=1
max-connection-per-server=5
input-file=G:\newFile\aria2.session
save-session=G:\newFile\aria2.session
enable-rpc=true
rpc-listen-port=6800
rpc-secret=xxxdownloader
4.2 运行方式:windows 命令行,提供jsonrpc服务,完整命令行为:
%pathto%\aria2c --conf-path=e:\web\Lab\aria2-1.31.0\aria2.conf
或
%pathto%\aria2c --conf-path=c:\tools\oss_sync\aria2-1.31.0\aria2.conf
# 在我的开发环境里,是这样的:
e:\web\Lab\aria2-1.31.0\aria2c.exe --conf-path=e:\web\Lab\aria2-1.31.0\aria2.conf
# 在 192.168.0.55 上,是这样的:
c:\vjtools\oss_sync\aria2-1.31.0\aria2c.exe --conf-path=c:\vjtools\oss_sync\aria2-1.31.0\aria2.conf
4.3 注意,在不同的环境,需要修改 aria2.conf 中的session文件路径,不然会启动 aria2 错误
- 后台管理
5.1 任务列表显示,便于监控
5.2 统计:已完成、未完成、失败的数量及大小等 - 从本地加载预览视频:
6.1 在 192.168.0.55 上,IIS配置站点,根目录为 D:\flv,主机头为空,端口80;
6.2 在审核员主机,修改本机hosts,将 dmp4.vjshi.com 指向 192.168.0.55,即可;
处理OSS转码上线后的历史预览文件
- 筛选:192.168.0.55 上,预览视频文件截止2017-04-26,当天有 1516 个文件;
SELECT id,filename,fileext,posttime,filesize FROM ss_program WHERE posttime>=UNIX_TIMESTAMP('2017-4-25 0:0:0') AND posttime<=UNIX_TIMESTAMP('2017-4-25 23:59:59')
- 执行查询:
# 预览视频
# 4月27号的
INSERT INTO oss_syncqueue(programid,tasktype,bucket,name,size,created,status) SELECT id,2,'vjshi-data-mp4-dis',CONCAT(DATE_FORMAT(FROM_UNIXTIME(posttime), '%Y-%m-%d'),'/',filename,'.',fileext),filesize,unix_timestamp(),1 FROM ss_program WHERE posttime>=UNIX_TIMESTAMP('2017-4-27 0:0:0') AND posttime<=UNIX_TIMESTAMP('2017-4-27 23:59:59') AND isconvert='y';
# 4月28号到30号的
INSERT INTO oss_syncqueue(programid,tasktype,bucket,name,size,created,status) SELECT id,2,'vjshi-data-mp4-dis',CONCAT(DATE_FORMAT(FROM_UNIXTIME(posttime), '%Y-%m-%d'),'/',filename,'.',fileext),filesize,unix_timestamp(),1 FROM ss_program WHERE posttime>=UNIX_TIMESTAMP('2017-4-28 0:0:0') AND posttime<=UNIX_TIMESTAMP('2017-4-30 23:59:59') AND isconvert='y';
# 截至 2017-5-3 18:0:0
INSERT INTO oss_syncqueue(programid,tasktype,bucket,name,size,created,status) SELECT id,2,'vjshi-data-mp4-dis',CONCAT(DATE_FORMAT(FROM_UNIXTIME(posttime), '%Y-%m-%d'),'/',filename,'.',fileext),filesize,unix_timestamp(),1 FROM ss_program WHERE posttime>=UNIX_TIMESTAMP('2017-5-1 0:0:0') AND posttime<=UNIX_TIMESTAMP('2017-5-3 18:0:0') AND isconvert='y';
# 截至 2017-5-4 14:30:0
INSERT INTO oss_syncqueue(programid,tasktype,bucket,name,size,created,status) SELECT id,2,'vjshi-data-mp4-dis',CONCAT(DATE_FORMAT(FROM_UNIXTIME(posttime), '%Y-%m-%d'),'/',filename,'.',fileext),filesize,unix_timestamp(),1 FROM ss_program WHERE posttime>UNIX_TIMESTAMP('2017-5-3 18:0:0') AND posttime=UNIX_TIMESTAMP('2017-4-27 0:0:0') AND programposttime<=UNIX_TIMESTAMP('2017-4-28 0:0:0');
UPDATE oss_syncqueue SET bucket='',status=1 WHERE status=101 AND programposttime>=UNIX_TIMESTAMP('2017-4-27 0:0:0') AND programposttime<=UNIX_TIMESTAMP('2017-4-28 0:0:0');
# 可以更新了
UPDATE oss_syncqueue SET bucket='vjshi-data-mp4',status=1 WHERE tasktype=2 AND status=101 AND programposttime>=UNIX_TIMESTAMP('2017-4-27 0:0:0') AND programposttime<=UNIX_TIMESTAMP('2017-4-28 0:0:0');
附录一:数据表 oss_syncqueue
use vjhero;
set names utf8;
CREATE TABLE IF NOT EXISTS `oss_syncqueue` (
`id` int(12) unsigned NOT NULL AUTO_INCREMENT,
`programid` int(12) unsigned NOT NULL DEFAULT '0' COMMENT '资源id',
`tasktype` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '1=源文件,2=预览文件',
`bucket` varchar(50) NOT NULL COMMENT '所在',
`name` varchar(100) NOT NULL COMMENT 'Object name',
`lastmodified` char(24) NOT NULL COMMENT '文件更改时间',
`etag` char(32) NOT NULL COMMENT 'etag',
`type` varchar(32) NOT NULL COMMENT 'Object 类别(Normal,Multipart)',
`url` varchar(100) NOT NULL COMMENT 'OSS 完整路径',
`size` int(12) unsigned NOT NULL DEFAULT '0' COMMENT '文件大小',
`created` int(12) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
`status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '1=待下载,10=下载中,100=下载完成,101=下载失败',
`costtime` int(12) unsigned NOT NULL DEFAULT '0' COMMENT '下载消耗时间(单位:秒)',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
# 2017.5.4 青年节快乐 -- 增加字段记录素材最初添加时间
alter table oss_syncqueue add column programposttime int(12) unsigned not null default 0 after programid;
# 更新该字段时间
update oss_syncqueue as S set programposttime=(select posttime from ss_program as P where S.programid=P.id);
附录二:aria2命令行下载文件
aria2c "http://xxx-data-upload.oss-cn-shanghai.aliyuncs.com/test/1121686_xxx_bce798826fa97314d17.mov?OSSAccessKeyId=LTAI9FQWL5nbY6kt&Expires=1493004269&Signature=fDO2mJ6f1v%2Fg6cjWe4%2B9YK%2FNNNA%3D" -d g:\newFile -o 1.mov -c
aria2c "http://xxx-data-upload.oss-cn-shanghai.aliyuncs.com/test/1121686_xxx_bce798826fa97314b0de365c6ef00d17.mov?OSSAccessKeyId=LTAI9FbY6kt&Expires=1493007542&Signature=uKk4nG8TldoFI%3D" -d g:\newFile -o 3.mov -c
aria2c "https://nj01ct01.baidupcs.com/file/15b78561c8c24987174a66db?bkt=p3-0000730a4e336669f1&fid=1778458740-250528-8644880266&time=1493005774&sign=FDTAXGERLBHS-DCbedcff06b081203-WJ7te8HYgi07eXJJi76Gzxs4Xws%3D&to=63&size=56666824&sta_dx=56666824&sta_cs=4&sta_ft=apk&sta_ct=2&sta_mt=0&fm2=MH,Yangquan,Netizen-anywhere,,sichuan,ct&newver=1&newfm=1&secfm=1&flow_ver=3&pkey=0000730a4ee11529bb956caffc3a336669f1&sl=83034191&expires=8h&rt=pr&r=145752607&mlogid=2632217428387618541&vuk=1778458740&vbdid=2477955945&fin=Qrsqloud-wandoujia-release-3-9-0.apk&fn=Qrsqloud-wandoujia-release-3-9-0.apk&rtype=1&iv=0&dp-logid=2632217428387618541&dp-callid=0.1.1&hps=1&csl=300&csign=Ugb%2BRCcZ876hmoDLg7t4l%2B2FC%2B4%3D&by=themis" -d g:\newFile -o 390.apk -c --file-allocation=falloc
附录三:通过 nodejs 调用 jsonrpc
- 安装node-websocket 模块
npm install websocket
- 封装 websocket 为 ./inc/lib/websocket.js,实现了 connect,send 等主要的调用方法
- 程序示例
var websocket = require('./websocket');
var options = {
'dir':'G:\\newfile\\2017-04-14',
'out':'f4f4cf36275.mov'
};
websocket.connect('ws://127.0.0.1:6800/jsonrpc', function() {
websocket.send({
method : 'aria2.addUri',
params : ['token:xxxxxxx',['http://data-upload.oss-cn-shanghai.aliyuncs.com/2017-04-24%2Ff4f4b06244b275.mov?OSSAccessKeyId=LTAbY6kt&Expires=1493104082&Signature=PuUv%2FgkzVRTI9x8%3D'], options]
}, function(result) {
console.log(result);
websocket.close();
});
});
- 接口返回数据
{
obj:{
id: '61a05552-37fa-4060-b8e9-871a35730dc1',
jsonrpc: '2.0',
result: '15f6171e0da5a6a0'
},
err: false
}
附录四:其他
- noejs 在对大文件(数据块)做操作时,存在内存泄漏风险,因此仅用于队列处理;
- 任务队列、文件下载的进度管理及相关异常处理
- 每天定时扫描文件,检查是否已经完成,对未完成的,再次通过jsonrpc接口提交下载任务,下载器将自动续传下载
- oss-sdk 生成的签名url有效期过后将无法下载,目前默认为1小时(3600)