前言

因为工作需要, 我开始接触流媒体

准备工作

其实一开始, 我对直播这块是不了解的;

首先, 说说流媒体是怎么运作的吧

流媒体其实像一个管道, 举例斗鱼的直播场景:

主播开启摄像头, 摄像头采集数据, 并将这些数据实时发送到斗鱼服务器 (推流)

然后, 大量观众们打开网址, 浏览器中的播放器与斗鱼服务器也进行实时的通信, 播放器读取数据展示在浏览器中 (拉流)

流程是如此, 但是实现的协议有好几种:

  • rtmp (延迟低, 兼容性不太好)
  • rtmp+websocket (rtmp的http实现方案, 个人认为有些复杂, 不适合我现在的场景)
  • hls (延迟较高, 苹果提出的基于 HTTP 的流媒体传输协议, 视频封装格式为ts, 但我观察b站对游戏竞赛场景(dota表演赛, 高并发场景)下使用的也是hls的方式, 待观察)
  • http-flv ((延迟低, 支持http,https播放)
  • webrtc (基于RTP/RTCP, 实时性好兼容性好, 能做到全平台兼容, 但似乎说如今还不完善, 待继续深入了解)
  • srs (流媒体服务器, 其定位是运营级的互联网直播服务器集群, 我打算将其部署到Linux平台中)

总而言之, 结合场景来选择方案吧

开发环境下, 我选择的是 OBS 进行推流 和 VLC 进行播放

不同的播放器拉流效果也是不一样的, VLC播放器好用但是延迟还是稍高些

我选择的方案是 http-flv + flv.js, 这样一来, 便可以无需Flash插件, 在浏览器进行 Html5 播放了

现如今了解的还只是皮毛,所以文章太过琐碎, 存在不少问题, 本文会持续更新的

  • 网络
    • TCP
    • UDP
  • 客户端
    • 缓冲
    • 累积延迟与跳帧(seek)处理
    • wasm
  • 服务端
    • GOP
    • ffmpeg推流优化
    • 多进程

正向代理与反向代理

正向代理隐藏真实客户端,反向代理隐藏真实服务端

正向代理

正向代理用途:

  • 访问原来无法访问的资源, 比如外网
  • 代理服务器可以用来做缓存, 加速访问
  • 在公司网络网关处搭设代理服务器, 对发起请求的客户端权限控制
  • 在公司网络网关处搭设代理服务器, 对发起请求的客户端做访问记录

反向代理

反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,
然后将请求转发给内部网络上的服务器,
并将从服务器上得到的结果返回给internet上请求连接的客户端,
此时代理服务器对外就表现为一个服务器。

通过在网络各处放置反向代理节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,
CDN系统能够实时地根据网络流量和各节点的连接、
负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。

反向代理的用途:

  • 保护, 隐藏服务端
  • 负载均衡, CDN

参考链接

今天有幸学习了文件转发这一块了

好久以前, 刚毕业的时候, 我就有想过这个问题, 最后还是不了了之

也确实如此, 文本, 数据传输这块在Web服务器是强项

由应用程序来实现对资源的控制 (权限, 积分规则等等)

应用程序内部对Web服务器通信 (发送特殊Header头)

Web服务器接收后进行特殊处理

然而ApacheNginx的请求头是不相同的, 如下有一张关于sendfile的表:

SENDFILE 头 Web服务器
X-Sendfile Apache, Lighttpd v1.5, Cherokee
X-LIGHTTPD-send-file Lighttpd v1.4
X-Accel-Redirect Nginx, Cherokee

话不多说, 看看在ApacheNginx下, 各自是如何配置的吧

Apache

Apache 需要 mod_xsendfile 的支持.

打开模块后, 发送header头时, 以文件真实路径发送过去即可

应用程序(PHP)则是发送Header头如下:

1
2
$filePath = '/mnt/d/somewhere/004.png';
header("X-Sendfile: $filePath");

Nginx

Nginx下多加了一步映射, 首先PHP代码如下:

1
header("X-Accel-Redirect: /customPath/$filePath");

Nginx里默认是支持 sendfile 的

配置如下:

1
2
3
4
location /customPath/ {
internal;
alias /wwwroot/path/path/; # 注意最後的斜杠
}
  1. nginx与php是如何通信的

如果php是运行在 workerman, swoole中的常驻内存应用中, 则通过参数 proxy_pass 反向代理去访问

如果php是运行在php-fpm的进程管理器中, 则通过参数 fastcgi_pass 去访问

fastcgi有两种形式:

tcp socket:

  1. 可以跨服务器通信
  2. 具有稳定性, tcp协议面向连接, 三次握手保证了通信的正确性和完整性

unix socket:

  1. 无需网络协议栈, 相较于tcp减少了资源开销
  2. 压力大时, 连接暴增会产生大量的长时缓存, 数据包不稳定

配置与多数据库

配置

redis 的配置文件位于 redis 的安装目录下, 文件名为: redis.conf

我们可以在 redis-cli 输入 CONFIG 命令查看当前 redis 的配置

1
2
config get loglevel
config get *

我们可以通过 config set 命令语法来修改配置

1
config set loglevel "notice"

常用的配置有:

命令 描述
daemonize no 表示是否启用守护进程
port 6379 指定 Redis 监听端口
bind 127.0.0.1 绑定的主机地址
timeout 300 客户端闲置多长时间后关闭连接,指定为0则表示关闭改功能
loglevel notice 指定日志记录级别
databases 16 设置数据库数量, 默认16
save 900 1 表示多长时间内, 有多少次更新时, 进行持久化

多数据库

redis 默认支持16个数据库.

当我们需要切换数据库时, 可以使用 select 命令

1
select 1

多个数据库之间并不是完全隔离的, 比如 flushall 命令可以清空整个 redis 实例中的所有数据库数据

因此, 一个 redis 实例应当对应一个应用, 不同编号的数据库可视为不同环境下的数据, 又或者以不同业务进行划分