分类目录归档:WEB服务

fredzneg与你一起对apache,nginx,squid,trafficserver学习相关知识及探讨!

nginx配置limit_conn_zone来限制并发连接数以及下载带宽

配置方法如下:



1、在nginx.conf里的http{}里加上如下代码:

  1. #ip limit
  2. limit_conn_zone $binary_remote_addr zone=perip:10m;
  3. limit_conn_zone $server_name zone=perserver:10m;

复制代码

2、在需要限制并发数和下载带宽的网站配置server{}里加上如下代码:

  1. limit_conn perip 2;
  2. limit_conn perserver 20;
  3. limit_rate 100k;

复制代码

补充说明下参数:

  • $binary_remote_addr是限制同一客户端ip地址;
  • $server_name是限制同一server最大并发数;
  • limit_conn为限制并发连接数;
  • limit_rate为限制下载速度;
转另一篇文章:http://hxl2009.blog.51cto.com/779549/1324473

注意:

nginx 1.1.8 之后的版本的语法改为limit_conn_zone $binary_remote_addr zone=NAME:10m;

NAME 就是 zone 的名字详情请看这里 http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html

限制连接数:

要限制连接,必须先有一个容器对连接进行计数,在http段加入如下代码:

“zone=” 给它一个名字,可以随便叫,这个名字要跟下面的 limit_conn 一致

$binary_remote_addr = 用二进制来储存客户端的地址,1m 可以储存 32000 个并发会话

… 省掉 N 字

http

{

limit_conn_zone $binary_remote_addr zone=addr:10m;

接下来需要对server不同的位置(location段)进行限速,比如限制每个IP并发连接数为1,则

server

{

listen 80;

server_name 192.168.11.128;

index index.html index.htm index.php;

limit_conn addr 1; #是限制每个IP只能发起1个连接 (addr 要跟 limit_conn_zone 的变量对应)

limit_rate 100k; #限速为 100KB/秒

root html;

注意事项:

limit_rate 100k; //是对每个连接限速100k。这里是对连接限速,而不是对IP限速!如果一个IP允许两个并发连接,那么这个IP就是限速limit_rate * 2

php日志错误分析:网站http返回502与504错误分析

一. 戏说
不管你是做运维还是做开发,哪怕你是游客,时不时会遇到502 Bad Gateway或504 Gateway Time-out。出现这页面,把服务重启下,再实在不行重启下服务器,问题就解决了,但是,这问题还是会困扰着你,特别是做运维的人员。夜黑风高正酣睡 时,一个电话响起,让你重启服务或IISRESET,肯定是极大不爽,立马要问候他妈了。呵呵,本文总结502与504故障分析与解决方法。

二. 状态码解释
502 Bad Gateway:作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
504 Gateway Time-out:作为网关或者代理工作的服务器尝试执行请求时,未能及时从上游服务器(URI标识出的服务器,例如HTTP、FTP、LDAP)或者辅助服务器(例如DNS)收到响应。

三. 502 Bad Gateway原因分析
将请求提交给网关如php-fpm执行,但是由于某些原因没有执行完毕导致php-fpm进程终止执行。说到此,这个问题就很明了了,与网关服务如php-fpm的配置有关了。
php-fpm.conf配置文件中有两个参数就需要你考虑到,分别是max_children和request_terminate_timeout。
max_children最大子进程数,在高并发请求下,达到php-fpm最大响应数,后续的请求就会出现502错误的。可以通过netstat命令来查看当前连接数。
request_terminate_timeout设置单个请求的超时终止时间。还应该注意到php.ini中的max_execution_time参数。当请求终止时,也会出现502错误的。
当积累了大量的php请求,你重启php-fpm释放资源,但一两分钟不到,502又再次呈现,这是什么原因导致的呢? 这时还应该考虑到数据库,查看下数据库进程是否有大量的locked进程,数据库死锁导致超时,前端终止了继续请求,但是SQL语句还在等待释放锁,这时 就要重启数据库服务了或kill掉死锁SQL进程了。
对于长时间的请求可以考虑使用异步方式,可以参阅《关于PHP实现异步操作的研究》。

四. 504 Gateway Time-out原因分析
504错误一般是与nginx.conf 配置有关了。主要与以下几个参数有关:fastcgi_connect_timeout、fastcgi_send_timeout、 fastcgi_read_timeout、fastcgi_buffer_size、fastcgi_buffers、 fastcgi_busy_buffers_size、fastcgi_temp_file_write_size、 fastcgi_intercept_errors。特别是前三个超时时间。如果fastcgi缓冲区太小会导致fastcgi进程被挂起从而演变为 504错误。

五. 小结
总而言之,502错误主要从四个方向入手:
1. max_children
2. request_terminate_timeout、max_execution_time
3. 数据库
4. 网关服务是否启动如php-fpm

504错误主要查看nginx.conf关于网关如fastcgi的配置

php日志分析:解决NGINX+PHP-FPM failed to ptrace(PEEKDATA) Input/output error出错问题

今天查看php的错误日志 (error_log = /usr/local/php/var/log/php-fpm.log )  和 慢日志(slowlog = /usr/local/php/var/log/php-fpm.log.slow ) ,  发现错误日志里很多  “ ERROR: failed to ptrace(PEEKDATA) pid 4276: Input/output error (5)  ”这样的错误 , 想找出出现这错误的原因于是从网上搜了如下的  文章 。他说是他的网站经常出现 ”bad gateway“ 错误才去查日志 发现有这个错误 。 我现在还不知道 我的 日志里出现这样的错误 是不是 我的页面也出现  ”bad gateway“ 的错误 。 带查证ing。

查了 好几个资料都说是 php开启了慢日志 引起的 为了让系统不出现异常 决定吧慢日志 注释掉。

request_slowlog_timeout = 30
slowlog = /usr/local/php/var/log/php-fpm.log.slow 

资料 一:

网站总是出现bad gateway 提示,时有,时无,查看了一下error_log日志,居然出现一堆错误,如下

[29-Mar-2014 22:40:10] ERROR: failed to ptrace(PEEKDATA) pid 4276: Input/output error (5)
[29-Mar-2014 22:53:54] ERROR: failed to ptrace(PEEKDATA) pid 4319: Input/output error (5)
[29-Mar-2014 22:56:30] ERROR: failed to ptrace(PEEKDATA) pid 4342: Input/output error (5)
[29-Mar-2014 22:56:34] ERROR: failed to ptrace(PEEKDATA) pid 4321: Input/output error (5)
[29-Mar-2014 22:56:40] ERROR: failed to ptrace(PEEKDATA) pid 4314: Input/output error (5)

网上也找了很多方法,很多人说是 rlimit_files 打开文件数的问题,但是觉得不太靠谱,最后找到鬼佬的话,看上去还有几分道理。

http://serverfault.com/questions/406532/i-o-error-with-php5-fpm-ptracepeekdata-failed

It appears you have request_slowlog_timeout enabled. This normally takes any request longer than N seconds, logs that it was taking a long time, then logs a stack trace of the script so you can see what it was doing that was taking so long.

In your case, the stack trace (to determine what the script is doing) is failing. If you’re running out of processes, it is because either:

After php-fpm stops the process to trace it, the process fails to resume because of the error tracing it
The process is resuming but continues to run forever.
My first guess would be to disable request_slowlog_timeout. Since it’s not working right, it may be doing more harm than good. If this doesn’t fix the issue of running out of processes, then set the php.ini max_execution_time to something that will kill the script for sure.

看样子是因为我打开了slowlog 然后,再设置 了 request_slowlog_timeout 这个参数,,所以后php 没有执行完就出错了。。

上面解决的办法是:

禁用 php-fpm.conf 里的 request_slowlog_timeout 和 slowlog ,然后,修改 php.ini 里的max_execution_time 参数

资料 二 :

最近服务器频繁出现502(nginx+php+php-fpm的架构),调试过程中在php-fpm的日志中发现了大量的:

[02-Aug-2014 08:55:24] ERROR: failed to ptrace(PEEKDATA) pid 4046: Input/output error (5)
[02-Aug-2014 08:55:24] NOTICE: finished trace of 4046
[02-Aug-2014 08:55:24] NOTICE: child 4047 stopped for tracing
[02-Aug-2014 08:55:24] NOTICE: about to trace 4047
[02-Aug-2014 08:55:24] ERROR: failed to ptrace(PEEKDATA) pid 4047: Input/output error (5)
[02-Aug-2014 08:55:24] NOTICE: finished trace of 4047
[02-Aug-2014 08:55:24] NOTICE: child 4054 stopped for tracing
[02-Aug-2014 08:55:24] NOTICE: about to trace 4054
[02-Aug-2014 08:55:24] ERROR: failed to ptrace(PEEKDATA) pid 4054: Input/output error (5)
[02-Aug-2014 08:55:24] NOTICE: finished trace of 4054
[02-Aug-2014 08:55:24] NOTICE: child 4076 stopped for tracing
[02-Aug-2014 08:55:24] NOTICE: about to trace 4076

经对比最近两次系统调优所使用的配置文件发现,是因为php-fpm的配置引起:

#request_slowlog_timeout = 5s
#slowlog = /usr/local/php/var/log/php-fpm.log.slow

解决办法是注释掉上面的配置即可。/etc/init.d/php-fpm restart生效

Nginx + FastCgi + Spawn-fcgi + c 的架构搭建

Php写的很有段时间了,最近看公司一些关键的后端CGI都是用C写的,以lighthttp 最为server 。忽然也有种学习用C写CGI的想法。虽然php结合php-fpm的fastcgi模式也有不错的性能,反正多学一种东西又有和不可以呢?何况,某些情况下C的性能还是php无法比拟的。



先有必要有这样第一个认识:ngxin作为一个webserver,本身并不包含CGI的解释器,需要通过一个中间件【例如php-fpm】来运行CGI。他们之间的模式大致是:

      nginx   <–   socket   –>   php-fpm——–>php  

那么nginx既然要运行c写的CGI那么也应该有类似php-fpm的东西。baidu, google了下,发现有一个spawn-fcgi的东西。原本是lighttp 内的fastcgi进程管理器。 于是又搜索了下,折腾了一个下午,终于抛出了经典的hello world !!!   。下面是具体步骤:

大致分为5步:

1、安装Spawn-fcgi    【启动cgi的时候需要】

wget   http://www.lighttpd.net/download/lighttpd-1.4.19.tar.gz tar zxvf  lighttpd-1.4.19.tar.gz    cd  lighttpd-1.4.19 ./configure make

复制 编译好的spawn-fcgi到 nginx目录,很主要!!!!

cp ./src/spawn-fcgi /usr/local/nginx/sbin/

2、安装fastcgi库:: 【提供编写cgi时的类库】

wget  http://www.fastcgi.com/dist/fcgi.tar.gz tar zxvf  fcgi.tar.gz cd  fcgi ./configure make make install

fcgio.cpp:50: error: ‘EOF’ was not declared in this scope解决办法PS:

我想这个fcgi开发一点也不活跃,而gcc的最新版本不断出来,很有可能是由于这方面引的原因,我又调整了一下关键字

gcc compile fcgi,(之前都是没有方向的搜索)。终于在第一条结果中找到原因了:http://bugs.gentoo.org/256654

解决办法:

在/include/fcgio.h文件中加上 #include <cstdio>,然后再编译安装就通过了。

3、测试代码::

#include <fcgi_stdio.h> int main( int argc, char *argv[] ) {   while( FCGI_Accept() >= 0 )   {       FCGI_printf( "Status: 200 OK\r\n" );       FCGI_printf( "Content-Type: text/html\r\n\r\n" );       FCGI_printf( "Hello world in C\n" );   }   return 0; }

编译::

g++ -o test.cgi test.cpp -L /usr/local/lib/ -lfcgi

4、启动Spawn-fcgi::

spawn-fcgi  -a 127.0.0.1 -p 7000 -u www  -f   /data/cgi-bin/test.cgi

如果报:   error while loading shared libraries: libfcgi.so.0: cannot open shared object file: No such file or directory  

请执行如下命令:为了这个错误,折腾了很长时间哦!

cp /usr/local/lib/libfcgi.so.0   /usr/lib

5、配置nginx.conf

  location ~ \.cgi$   {         fastcgi_pass  127.0.0.1:7000;         fastcgi_index index.cgi;         fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;         include fastcgi_params;     }

重启nginx

/etc/init.d/nginx reload

PHP-CGI与php-fpm的区别

php-cgi是被调用的进程,php-fpm是配置和管理进程的。

cgi效率低,每次来了PHP请求,新建立一个PHP进程来解析,解析完毕进程销毁,再来请求再起进程。。。

fpm=fastcgi process manage,维持一定数量的进程数,供nginx调用,不用每次都新建进程,速度更快。原理上有点类似于数据库连接池吧。

CGI 是用来接收HTTP请求的一个程序,例如[127.0.0.1/index.php?c=article&id=11,这个请求通过apahce、nginx等等过来,然后http服务器发送给php-cgi(就是php用来接收http的程序),这个玩意儿每次新建一个进程的时候都要读取和加载php.ini的一堆参数,然后才能开始接收请求,比较慢。

FASTCGI的工作原理是首先启动一个master,这个master加载了所有的配置信息等等,master会新建很多个worker,然后每次有请求的时候master负责把请求分配给相应的worker,这样避免了重复加载和启动,就是一个提交cgi程序效能的东西,fastcgi这个东西只是一个协议(你可以理解为是一个没实现的想法),并不是一个程序。

PHP-FPM就是实现这个想法的程序,CGI很蠢,不会管理进程,而PHP-FPM会根据实际情况,创建worker或者关掉worker进程,保持一定量的worker,请求多了,worker就多了,请求少了,worker就会被关掉一部分,你可以理解为它是一个高效CGI的进程管理器。

nginx通过GeoIP模块限制国家地区用户访问(Debian/Ubuntu/CentOs环境)

本文介绍如何使用GeoIP模块让nginx实现限制某个地区用户访问的功能。nginx要加上 –with-http_geoip_module 参数进行编译。

1、首先我们检查一下nginx是否编译了GeoIP模块

nginx -V

如果你在输出界面看到了 –with-http_geoip_module,那么就说明nginx已经编译了GeoIP模块。

2、接下来我们安装GeoIP数据库
在Debian/Ubuntu系统,我们可以执行下面的命令进行安装:

apt-get install geoip-database libgeoip1

CentOS安装办法:  yum -y install geoip-devel

安装完成之后,GeoIP数据库会被安装在 /usr/share/GeoIP/GeoIP.dat。

这个GeoIP.dat是GeoIP数据库文件,使用apt-get命令安装的话这个文件不是最新的,我们可以从 http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz 这里下载最新的GeoIP数据库文件。

mv /usr/share/GeoIP/GeoIP.dat /usr/share/GeoIP/GeoIP.dat_bak

cd /usr/share/GeoIP/
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
gunzip GeoIP.dat.gz

3、现在来配置nginx.conf文件

vi /etc/nginx/nginx.conf

将下面的内容添加进 http {} 区域,并且要放在任何 include 语句之前。

geoip_country /usr/share/GeoIP/GeoIP.dat;
map $geoip_country_code $allowed_country {
default yes;
FK no;
FM no;
EH no;
}

上面这些语句是除了 FK,FM,EH这三个地区的用户允许其它地区的用户访问。

也可以只允许部分地区用户访问:

geoip_country /usr/share/GeoIP/GeoIP.dat;
map $geoip_country_code $allowed_country {
default no;
FK yes;
FM yes;
EH yes;
}

上面这些语句是除了 FK,FM,EH这三个地区的用户其它地区的用户都不允许访问。

上面的语句只是设置了一个 $allowed_country 变量,要最终实现禁止设置的地区用户访问,我们要对 $allowed_country 变量进行判断处理。
在 server {} 区域里添加以下内容:

if ($allowed_country = no) {
return 403;
}

也可以针对某个特定url进行限制:

location /special {
if ($allowd_country = no) {
return 403;
}
}

配置 中国用户访问其他目录 nginx,在相关地方加上如下的配置就可以了:

# vi /etc/nginx/nginx.conf

http {
...
geoip_country /home/vpsee/GeoIP.dat;
fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
fastcgi_param GEOIP_COUNTRY_CODE3 $geoip_country_code3;
fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name;
...
}

server {
...
        location / {
            root   /home/vpsee/www;
            if ($geoip_country_code = CN) {
                root /home/vpsee/cn;
            }
            ...
        }
...
}

这样,当来自中国的 IP 访问网站后就自动访问到预定的 /home/vpsee/cn 页面。关于 Nginx + GeoIP 还有很多有用的用法,比如做个简单的 CDN,来自中国的访问自动解析到国内服务器、来自美国的访问自动转向到美国服务器等。MaxMind 还提供了全球各个城市的 IP 信息,还可以下载城市 IP 数据库来针对不同城市做处理。

4、重启nginx

/etc/init.d/nginx reload

这样我们就实现了nginx限制某个地区用户访问的功能。

Nginx目录限制执行php文件

Nginx目录限制执行php文件?限制目录执行php文件方法有很多,像apache就可以搞定,iis也可以搞定,下面我来介绍在nginx中限制指定目录执行 php文件方法
方法
 代码如下 复制代码
location~^/images/.*\.(php|php5)$
{
denyall;
}
location~^/static/.*\.(php|php5)$
{
denyall;
}
location~*^/data/(attachment|avatar)/.*\.(php|php5)$
{
denyall;
}
注:这些目录的限制必须写在
 代码如下 复制代码
location~.*\.(php|php5)$
{
fastcgi_pass  127.0.0.1:9000;
fastcgi_index  index.php;
include fcgi.conf;
}
的前面,否则限制不生效!
path_info漏洞修正:
在通用fcgi.conf顶部加入
 代码如下 复制代码
if ($request_filename ~* (.*)\.php) {
set $php_url $1;
}
if (!-e $php_url.php) {
return 404;
}

1、去除单个目录去掉PHP执行权限
 代码如下 复制代码
location ~ /attachments/.*\.(php|php5)?$ {
deny all;
}
2、多个目录去掉PHP执行权限
 代码如下 复制代码
location ~ /(attachments|upload)/.*\.(php|php5)?$ {
deny all;
}
如果你想在apache中限制执行php可参考
以设置APACHE的虚拟主机配置项,是使其不能执行PHP程序
如果用.htaccess来实现某个目录需要认证,则在apache的httpd.conf里设置:
 代码如下 复制代码
<Directory /dir>  
Options Indexes FollowSymLinks  
AllowOverride AuthConfig  
order deny,allow  
</Directory>
然后在需要认证的目录(如:dir)下建立.htaccess文件

最全解决方法phpcms V9 前台和后台登陆验证码无法显示问题

首先说过下 如果问题帮您解决了 你们就回复一下 顶一下帖子 我不喜欢设置回复 因为很多人根本就没有注册论坛账号所以进来看到了自己需要的答案  而被设置了要回复才能看到的时候 他们就会去注册 但是注册了要60分钟后才能回复 所以很急人的(我亲身体验 苦苦等了60分钟)   所以 你们喜欢的 解决问题的 记得顶帖子 我会爱死你们的 呵呵

好了不废话了 下面发解决方法



1:首先第一种(我就是用这个方法解决的,很多人用的是免费空间,但是往往免费空间是没有客服的 所以我们只能靠自己来解决了。)

可以偿试通过修改”/caches/configs/system.php”当中的:



‘session_storage’ => ‘mysql’,



将其修改为



‘session_storage’ => ‘files’,



然后保存下来 上传进去的时候选择覆盖(右键-打开方式-文本文件打开)

然后清除自己浏览器的COOKS  再次登录后台(这里再提供一下  如果你首次安装的时候是乱码的    您可以通过FTP连接后找到caches这个目录下configs这个文件夹下的system.php,下载到本地,修改其中的gzip => 1,其中的1改为0保存然后上传覆盖就可以了

)_





2:如果不是路径问题 也不是CD库问题

解决办法:重启APACHE服务器





3:

找到

./phpcms/libs/classes/session_mysql.class.php
./phpsso_server/phpcms/libs/classes/session_mysql.class.php
(其实这个文件我是在Web/phpsso_server/caches/configs/ 找到的   这一个解决方法我是在百度找到的 如果有疑问可以不要试  )



phpcms/libs/classes/session_mysql.class.php



将行21:session_start();放到行20:session_set_save_handler(array(&$thi….

之前

结论:官方的代码不规范

然后清除自己浏览器的COOKS  再次登录后台













以上方法为我亲自试验过的  目前是第一个方法我成功了  如果有不对的地方还请明示  如果好 还请版主帮我加精 谢谢啦

低延时直播应用

直播应用中,RTMP和HLS基本上可以覆盖所有客户端观看(参考:DeliveryHLS),HLS主要是延时比较大,RTMP主要优势在于延时低。

低延迟的部署实例参考:Usage: Realtime

应用场景

低延时应用场景包括:

  • 互动式直播:譬如2013年大行其道的美女主播,游戏直播等等各种主播,流媒体分发给用户观看。用户可以文字聊天和主播互动。
  • 视频会议:SRS的DEMO就有视频会议应用,我们要是有同事出差在外地,就用这个视频会议开内部会议。其实会议1秒延时无所谓,因为人家讲完话后,其他人需要思考,思考的延时也会在1秒左右。当然如果用视频会议吵架就不行。
  • 其他:监控,直播也有些地方需要对延迟有要求,互联网上RTMP协议的延迟基本上能够满足要求。

RTMP和延时

RTMP的特点如下:

  • Adobe支持得很好:RTMP实际上是现在编码器输出的工业标准协议,基本上所有的编码器(摄像头之类)都支持RTMP输出。原因在于PC市场巨大,PC主要是Windows,Windows的浏览器基本上都支持flash,Flash又支持RTMP支持得灰常好。
  • 适合长时间播放:因为RTMP支持的很完善,所以能做到flash播放RTMP流长时间不断流,当时测试是100万秒,即10天多可以连续播放。对于商用流媒体应用,客户端的稳定性当然也是必须的,否则最终用户看不了还怎么玩?我就知道有个教育客户,最初使用播放器播放http流,需要播放不同的文件,结果就总出问题,如果换成服务器端将不同的文件转换成RTMP流,客户端就可以一直播放;该客户走RTMP方案后,经过CDN分发,没听说客户端出问题了。
  • 延迟较低:比起YY的那种UDP私有协议,RTMP算延迟大的(延迟在1-3秒),比起HTTP流的延时(一般在10秒以上)RTMP算低延时。一般的直播应用,只要不是电话类对话的那种要求,RTMP延迟是可以接受的。在一般的视频会议(参考SRS的视频会议延时)应用中,RTMP延时也能接受,原因是别人在说话的时候我们一般在听,实际上1秒延时没有关系,我们也要思考(话说有些人的CPU处理速度还没有这么快)。
  • 有累积延迟:技术一定要知道弱点,RTMP有个弱点就是累积误差,原因是RTMP基于TCP不会丢包。所以当网络状态差时,服务器会将包缓存起来,导致累积的延迟;待网络状况好了,就一起发给客户端。这个的对策就是,当客户端的缓冲区很大,就断开重连。当然SRS也提供配置。

HLS低延时

主要有人老是问这个问题,如何降低HLS延迟。

HLS解决延时,就像是爬到枫树上去捉鱼,奇怪的是还有人喊,看那,有鱼。你说是怎么回事。

我只能说你在参与谦哥的魔术表演,错觉罢了。

如果你真的确信有,请用实际测量的图片来展示出来,参考下面延迟的测量。

RTMP延迟的测量

如何测量延时,是个很难的问题,不过有个行之有效的方法,就是用手机的秒表,可以比较精确的对比延时。参考:RTMP延时测量

经过测量发现,在网络状况良好时:

  • RTMP延时可以做到0.8秒左右(SRS也可以)。
  • 多级边缘节点不会影响延迟(和SRS同源的某CDN的边缘服务器可以做到)
  • Nginx-Rtmp延迟有点大,估计是缓存的处理,多进程通信导致?
  • GOP是个硬指标,不过SRS可以关闭GOP的cache来避免这个影响,参考后面的配置方法。
  • 服务器性能太低,也会导致延迟变大,服务器来不及发送数据。
  • 客户端的缓冲区长度也影响延迟。譬如flash客户端的NetStream.bufferTime设置为10秒,那么延迟至少10秒以上。

GOP-Cache

什么是GOP?就是视频流中两个I帧的时间距离,如果问什么是I帧就去百度。

GOP有什么影响?Flash(解码器)只有拿到GOP才能开始解码播放。也就是说,服务器一般先给一个I帧给Flash。可惜问题来了,假设GOP是10秒,也就是每隔10秒才有关键帧,如果用户在第5秒时开始播放,会怎么样?

第一种方案:等待下一个I帧,也就是说,再等5秒才开始给客户端数据。这样延迟就很低了,总是实时的流。问题是:等待的这5秒,会黑屏,现象就是播放器卡在那里,什么也没有,有些用户可能以为死掉了,就会刷新页面。总之,某些客户会认为等待关键帧是个不可饶恕的错误,延时有什么关系?我就希望能快速启动和播放视频,最好打开就能放!

第二种方案:马上开始放,放什么呢?你肯定知道了,放前一个I帧。也就是说,服务器需要总是cache一个gop,这样客户端上来就从前一个I帧开始播放,就可以快速启动了。问题是:延迟自然就大了。

有没有好的方案?有!至少有两种:

  • 编码器调低GOP,譬如0.5秒一个GOP,这样延迟也很低,也不用等待。坏处是编码器压缩率会降低,图像质量没有那么好。
  • 服务器提供配置,可以选择前面两个方案之一:SRS就这么做,有个gop_cache配置项,on就会马上播放,off就低延迟。

SRS的配置项:

# the listen ports, split by space. listen              1935; vhost __defaultVhost__ { # whether cache the last gop. # if on, cache the last gop and dispatch to client, #   to enable fast startup for client, client play immediately. # if off, send the latest media data to client, #   client need to wait for the next Iframe to decode and show the video. # set to off if requires min delay; # set to on if requires client fast startup. # default: on gop_cache       on; }

备注:参考conf/full.conf的min.delay.com配置。

累积延迟

除了GOP-Cache,还有一个有关系,就是累积延迟。SRS可以配置直播队列的长度,服务器会将数据放在直播队列中,如果超过这个长度就清空到最后一个I帧:

vhost your_vhost { # the max live queue length in seconds. # if the messages in the queue exceed the max length,  # drop the old whole gop. # default: 30 queue_length    10; }

当然这个不能配置太小,譬如GOP是1秒,queue_length是1秒,这样会导致有1秒数据就清空,会导致跳跃。

有更好的方法?有的。延迟基本上就等于客户端的缓冲区长度,因为延迟大多由于网络带宽低,服务器缓存后一起发给客户端,现象就是客户端的缓冲区变大了,譬如NetStream.BufferLength=5秒,那么说明缓冲区中至少有5秒数据。

处理累积延迟的最好方法,是客户端检测到缓冲区有很多数据了,如果可以的话,就重连服务器。当然如果网络一直不好,那就没有办法了。

低延时配置

考虑GOP-Cache和累积延迟,推荐的低延时配置如下(参考min.delay.com):

# the listen ports, split by space. listen              1935; vhost __defaultVhost__ { # whether cache the last gop. # if on, cache the last gop and dispatch to client, #   to enable fast startup for client, client play immediately. # if off, send the latest media data to client, #   client need to wait for the next Iframe to decode and show the video. # set to off if requires min delay; # set to on if requires client fast startup. # default: on gop_cache       off; # the max live queue length in seconds. # if the messages in the queue exceed the max length,  # drop the old whole gop. # default: 30 queue_length    10; }

当然,服务器的性能也要考虑,不可以让一个SRS进程跑太高带宽,一般CPU在80%以下不会影响延迟,连接数参考性能

实测

SRS: 0.9.55

编码器:FMLE, video(h264, profile=baseline, level=3.1, keyframe-frequency=5seconds), fps=15, input=640×480, output(500kbps, 640×480), 无音频输出(FMLE的音频切片HLS有问题)

网络:推流为PC在北京公司内网,观看为PC北京公司内网,服务器为阿里云青岛节点。

服务器配置:

listen              1935; vhost __defaultVhost__ {
    enabled         on; gop_cache       off; hls {
        enabled         on; hls_path        ./objs/nginx/html; hls_fragment    5; hls_window      20; }
}

结论:RTMP延迟2秒,HLS延迟24秒。

参考:RTMP-HLS-latency

Edge实测

SRS集群不会增加延迟。这个是Edge模式比ingest要高级的地方,ingest需要启动进程,延迟会大。ingest主要适配多种协议,也可以主动从源站采集流,但Edge是专业的边缘模式。

参考:Edge-latency

Winlin 2014.2

怎么能够像爱奇艺、腾讯那样玩实时直播

大家都知道爱奇艺、腾讯在直播版权上烧钱最凶,而且直播体验也不错。实时直播做的好需要神秘配方,其中有一味重要调料:他们都用HTTP FLV!

那么我们这一节详细解释HTTP
FLV的背景。

Whatis HTTP
FLV

所有的HTTPFLV流都是一个HTTP FLV地址,譬如:http://ossrs.net:8081/live/livestream.flv,但是,流的形式却至少有三种:

1. FLV文件,渐进式HTTP流。放一个文件到nginx目录,可以访问下载在播放器播放,这是HTTP FLV文件,也就是渐进式下载流。所谓渐进式下载,也就是用户观看时无法从未下载的地方开始看。

2. FLV伪流。一般说的HTTP FLV,比上面的渐进式流高级一点,譬如,一个120分钟的电影,作为渐进式流播放时,用户需要从60分钟开始看,如何支持呢?因为nginx是当做文件下载的,无法直接跳转到第60分钟(nginx也不知道60分钟对应的字节偏移是多少呀)。后来有人就支持这种跳着播放,通过指定时间服务器从指定的位置开始给流,这种支持flv?start=,就是httpflv的伪流,本质上还是点播流。

3. FLV直播流。SRS所指的HTTPFLV流,是严格意义上的直播流,有RTMP的所有特征,譬如集群、低延迟、热备、GOPcache,而且有HTTP的优势,譬如302、穿墙、通用。由于SRS内部实现了HTTP服务器,所以SRS是在边缘将RTMP流转换成HTTP流,SRS集群内部还是使用RTMP分发。当前唯一将RTMP和HTTP协议都解析的服务器,目前只有SRS和nginx-rtmp,可惜nginx-rtmp没有实现这个流。

用一句话概括,SRS的HTTP FLV就是增强的RTMP,真正的实时流媒体分发。

ConfuseHTTP
FLV

SRS的HTTP FLV容易和下面的几种分发方式混淆:

1. RTMPT:这个实际上是最接近SRS的HTTP FLV的概念的。但是从本质上来讲,rtmpt是基于HTTP的RTMP,所以还是RTMP而不是FLV。

2. HDL/HFL:国内一些厂家的HXX流,就是FLV流,主要和SRS的区别在于服务器集群内部SRS还是走RTMP,所以延迟可能会有很大差异。SRS的HTTP FLV和RTMP延迟一样,0.8-3秒。

3. HDS:这个差的太远了,不是一个东西。HDS和HLS像,但是HTTP FLV和他们两个都完全不像。

WhyHTTP
FLV

为何要整个HTTPFLV出来呢?当下HTTP FLV流正大行其道。主要的优势在于:

1. 互联网流媒体实时领域,还是RTMP。HTTP-FLV和RTMP的延迟一样,因此可以满足延迟的要求。

2. 穿墙:很多防火墙会墙掉RTMP,但是不会墙HTTP,因此HTTPFLV出现奇怪问题的概率很小。

3. 调度:RTMP也有个302,可惜是播放器as中支持的,HTTP FLV流就支持302方便CDN纠正DNS的错误。

4. 容错:SRS的HTTP FLV回源时可以回多个,和RTMP一样,可以支持多级热备。

5. 通用:Flash可以播RTMP,也可以播HTTPFLV。自己做的APP,也都能支持。主流播放器也都支持httpflv的播放。

6. 简单:FLV是最简单的流媒体封装,HTTP是最广泛的协议,这两个到一起维护性很高,比RTMP简单多了。