年轻司机介绍补预告片系统架构与cgi

作者: | 更新日期:

作为一个年轻的司机, 来公司已经两年了。刚来的时候,做了补预告片系统,现在简单介绍一下.

本文首发于公众号:天空的代码世界,微信号:tiankonguse

概要

这篇文章简单的记录做的一个简单的系统, 并介绍一下cgi相关的知识点.

项目背景

视频是一个用户粘性很低的行业.
而我们部门在这个行业刚起步, 很多视频内容都不完善, 即只有一个空专辑(比如XX电影的名字).
我曾问上级, 为什么不买往年的热门电影.
回答是: 对于往年的电影 如果现在去花钱买那些版权收益也不大, 对于以后的, 都是我们的, 都会买.
但是一个电影的预告片往往是不需要版权的, 所以这里就希望可以对往年的电影补充预告片, 这样用户进到这个专辑, 至少可以看几分钟相关的宣传内容.

项目介绍

这个项目的目的是给空专辑补充预告片.
由于是从无到有的过程, 需要快速支持, 不需要做一个完善的闭环系统.

这里分两个子项目:

  1. 已经有空专辑和预告片视频了. 我们需要通过某种方法识别他们(豆瓣ID), 然后关联起来.
  2. 只有一个空专辑, 没有预告片. 我们需要去互联网上抓取预告片, 然后关联起来.

系统的架构图大概如下:

项目实现

项目实际上分为几个模块(实际项目中对步骤进行调整优化了).

  1. 把空专辑与单视频通过豆瓣ID关联起来.
    大概步骤如下:
    1). 从A表中找到符合指定条件的空专辑
    2). 从B表中找到专辑对应的豆瓣ID, 做豆瓣ID到专辑的反向关系(存在多个时, 保留最后一个专辑)
    3). 从C表找到符合条件的单视频
    4). 从D表找到单视频对应的豆瓣ID, 做豆瓣ID到视频的反向关系(存在多个时, 全部保留)
    5). 扫表专辑的豆瓣ID列表, 在视频列表中看是否存在, 存在则把关系保存起来
    6). 把找到的专辑和视频通过接口关联起来.

  2. 对于没关联的空专辑抓取视频
    这个步骤看上面的流程图就很清晰了.

  3. 需要有个简单的系统供编辑处理
    1). 添加任务
    2). 展示任务列表
    3). 编辑处理任务(编辑是否补上预告片)
    4). 每日邮件发送统计情况

做这个项目的时候, 第一步和第三步是一期做的.这样可以快速的补充大量的预告片, 且准确度很高.
第二部分是二期做的, 需要抓取团队开发对应的功能, 而且由于是使用标题等资料搜索抓取的, 准确度很低很低.

优化

这个项目有个特点: 快速实现.
对于内部空专辑和单视频关联逻辑, 没什么优化的, 历史数据跑完了, 关联的数据就几乎为0了.
抓取视频的准确度较低, 倒是可以优化, 但是我们是以产品驱动的, 这个项目还没上线时就已经投入其他项目了(还好上线后编辑使用没出任何问题).
所以这个项目的总体架构就是上图介绍的.

项目结语

做上面项目第一期的时候, 实际上工作分为两部分:

  1. 一个简单的系统
  2. 编写关联程序, 调用系统接口添加任务.

做系统的时候, 发现周围的人都使用C++当做WEB服务器的后台开发语言, 他们还称此为cgi.
于是有必要了解一下cgi.

cgi介绍

CGI 的中文是通用网关接口.
阅读了WIKI, 发现把我们写的c++程序称为CGI是不恰当的.
因为CGI只是WEB服务器与动态处理程序之间的一个标准或协议, 我们平时写的php, python, perl和c++的二进制没有太大的区别, 都是接收请求, 处理, 返回结果.

当认识到CGI只是一个协议时, 我们心里自然就会想问另一个问题: WEB服务器与动态处理程序之间是什么关系?

答案也很快得到验证.

接着想到的第二个问题是: WEB服务器怎么识别我们的动态处理程序的.

这个问题其实是两个问题.

  1. WEB服务器怎么知道这个请求需要动态处理程序处理.
  2. WEB服务器怎么知道怎么执行这个动态处理程序.

对于第一个问题, WEB服务器往往是通过请求URL匹配的方式识别的.
对于第二个问题, 其实在linux上很容易回答: linux是怎么识别我们的脚本的?

在apache上, 我们通常使用ScriptAlias来指定程序的位置.
而在nginx上, 我们则需要一个额外的调度器来调用对应的程序.

可以看看下面的测试程序, 我们用bash脚本也可以做网站了.

[user_00@V_10_157_52_39 /data/release/vunion.oa.com/cgi-bin]$ cat ./test.sh
#!/bin/sh
echo -e "Content-type:text/html\n\n"
echo -e "hello<br>"
echo -e "$0  $*<br>"
echo -e "${SCRIPT_NAME}<br>"
echo -e "${QUERY_STRING}<br>"

最后, 我们的问题是: 怎么传输数据的?

这个问题其实反而好回答了.
我们看看上面的bash脚本, 输入数据并没有使用参数传输.
对于bash, 传参有两种: 参数和环境变量.
CGI标准使用的是环境变量来传参的.

而对于输出数据, 直接使用标准输出来传送数据了(不考虑 std_err).

扩展问题: 我们使用什么框架来编写cgi

开源, 开源, 开源!!!
我们cgi基础框架是开源软件: clearsilver, 它封装了cgi相关操作.
然后前辈在clearsilver的基础上, 封装了一个cgiframe框架. 开发只需要实现两个函数即可: init初始化函数, process 逻辑处理函数.
这里就不多说了, 封装的好处是大家开发快, 缺点是很多人都不知道底层的原理了.

问题定位

这里把c++编写的程序称为WEB程序更合适点.
对于C++ 编译型WEB程序, 定位问题一般是固定的.

  1. 万能定位法: 打日志
  2. 常驻进程定位法: gdb + strace.

有人可能会说, cgi一般会先 fork 一个进程出来, 这个怎么定位呢?

其实答案很简单, gdb进入fork对应的进程即可, strace 进入fork对应的进程即可.

gdb: set follow-fork-mode child
strace: man strace  # 我不会告诉你是-f参数

结语

年轻的司机语言表达能力不好, 结构的组织能力也不好.

其实要表达的有两点:

  1. 我们所在的部门起步较晚, 很多基础功能都没有, 但这不是理由, 我们会努力去做好一切的, 有问题可以随时反馈.
  2. cgi是进来接触的第一个知识点, 了解了原理后, 会发现什么语言编写的其实都一样的.

本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。

关注公众号,接收最新消息

tiankonguse +
穿越