星域CDN(即迅雷CDN)价格表,最便宜500Gbps峰值带宽9999元/G/月,小于5G 12999元/G/月

根据星域CDN(迅雷CDN)官网公布当你的带宽达到500Gbps才是9999元/G/月,但绝对部分用户达不到这个,我想应该都是5G以下,价格是12999元/G/月,星域CDN(迅雷CDN)价格原网参考如下:

适用方案:视频点播、游戏下载、移动应用、智能硬件

计费方式 使用量级 单价
带宽计费 0–5Gbps 12999元/G/月
5–50Gbps 11999元/G/月
50–500Gbps 10999元/G/月
500Gbps以上 9999元/G/月
流量计费 0–50TB 0.15元/GB
50TB–0.5PB 0.13元/GB
0.5PB–50PB 0.12元/GB
50PB以上 0.10元/GB

适用方案:视频直播

计费方式 使用量级 单价
带宽计费 不限 15000元/G/月

*充值用户享受官网阶梯价格累计。

*预付费购买流量,按日使用流量,在监控平台可以查询流量明细。

申请完成后,迅雷会发送一封激活邮件:

QQ截图20150910162707.jpg

点击邮件即可以激活500G

QQ截图20150910162849.jpg

星域CDN(迅雷CDN)价格原网参考:http://xycdn.com/site/price

最全解决方法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  再次登录后台













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

centos下,使用postfix实现php发送mail功能

1、centos下安装postfix,执行命令:

# yum -y install postfix popa3d

如果不需要pop3服务,把popa3d去掉

2、在php.ini配置文件上,设置mail函数:
1)打开php.ini配置,下面是我的php.ini路径:

# vi /usr/local/php/etc/php.ini


2)找到:sendmail_path ,将其设置为:


sendmail_path = /usr/sbin/sendmail -t

注意:这里需要先到/usr/sbin/ 目录中,确认是否存在sendmail文件。

3、启动postfix:

# /etc/init.d/postfix start

4、重启php-fpm:

# /etc/init.d/php-fpm  restart

5、以上完成。你可以写一个发送email的php文件做测试,如下:

<?php
$send = mail(‘yourEmail@test.com’, ‘My Subject’, ‘The test mail’);
if($send){
echo ‘true’;
}else{
echo ‘false’;
}
?>
以上,运行如果显示true,则,你将会在‘yourEmail@test.com’中收到一封主题为’My Subject’的email。

 

如果要限制外来主机访问smtp服务,修改/etc/postfix/main.cf里的

inet_interfaces=all

inet_interfaces=localhost

Mysql CPU占用高原因分析及解决方法

最近发现php网站发布信息比较慢,而且同网站目录下的php经常登录后立即就重新登录,立即考虑到服务器资源占用问题,所以进服务器看到原来mysql占用率较高 25-60%左右,偶尔能跑到100%,所有导致上述问题的发生

通过以前对mysql的操作经验,先将mysql的配置问题排除了,查看msyql是否运行正常,通过查看mysql data目录里面的*.err文件(将扩展名改为.txt)记事本查看即可。如果过大不建议用记事本了,容易死掉,可以用editplus等工具



简单的分为下面几个步骤来解决这个问题:



1、mysql运行正常,也有可能是同步设置问题导致



2、如果mysql运行正常,那就是php的一些sql语句导致问题发现,用root用户进入mysql管理

mysql -u root -p

输入密码

mysql:show processlist 语句,查找负荷最重的 SQL 语句,优化该SQL,比如适当建立某字段的索引。



通过这个命令我看到原来是有人恶意刷搜索,因为dedecms搜索后面调用搜索最高的词,导致很多人用工具刷这个,而且是定时有间隔的,所以将这个php程序改名跳转都方法解决了。



当然如果你的确实是sql语句用了大量的group by等语句,union联合查询等肯定会将mysql的占用率提高。所以就需要优化sql语句,网站尽量生成静态的,一般4W ip的静态网站,mysql占用率几乎为0的。所以这对于程序员的经验是个考虑。尽量提高mysql性能 (MySQL 性能优化的最佳20多条经验分享)



下面是脚本之家收集的文章,大家都可以参考下
MYSQL CPU 占用 100% 的现象描述 



早上帮朋友一台服务器解决了 Mysql cpu 占用 100% 的问题。稍整理了一下,将经验记录在这篇文章里 

朋友主机(Windows 2003 + IIS + PHP + MYSQL )近来 MySQL 服务进程 (mysqld-nt.exe) CPU 占用率总为 100% 高居不下。此主机有10个左右的 database, 分别给十个网站调用。据朋友测试,导致 mysqld-nt.exe cpu 占用奇高的是网站A,一旦在 IIS 中将此网站停止服务,CPU 占用就降下来了。一启用,则马上上升。 



MYSQL CPU 占用 100% 的解决过程 



今天早上仔细检查了一下。目前此网站的七日平均日 IP 为2000,PageView 为 3万左右。网站A 用的 database 目前有39个表,记录数 60.1万条,占空间 45MB。按这个数据,MySQL 不可能占用这么高的资源。 



于是在服务器上运行命令,将 mysql 当前的环境变量输出到文件 output.txt: 



d:\web\mysql> mysqld.exe –help >output.txt 

发现 tmp_table_size 的值是默认的 32M,于是修改 My.ini, 将 tmp_table_size 赋值到 200M: 



d:\web\mysql> notepad c:\windows\my.ini 

[mysqld] 

tmp_table_size=200M 



然后重启 MySQL 服务。CPU 占用有轻微下降,以前的CPU 占用波形图是 100% 一根直线,现在则在 97%~100%之间起伏。这表明调整 tmp_table_size 参数对 MYSQL 性能提升有改善作用。但问题还没有完全解决。 



于是进入 mysql 的 shell 命令行,调用 show processlist, 查看当前 mysql 使用频繁的 sql 语句: 



mysql> show processlist; 

反复调用此命令,发现网站 A 的两个 SQL 语句经常在 process list 中出现,其语法如下: 



SELECT t1.pid, t2.userid, t3.count, t1.date 

FROM _mydata AS t1 

LEFT JOIN _myuser AS t3 ON t1.userid=t3.userid 

LEFT JOIN _mydata_body AS t2 ON t1.pid=t3.pid 

ORDER BY t1.pid 

LIMIT 0,15 

调用 show columns 检查这三个表的结构 : 



mysql> show columns from _myuser; 

mysql> show columns from _mydata; 

mysql> show columns from _mydata_body; 

终于发现了问题所在:_mydata 表,只根据 pid 建立了一个 primary key,但并没有为 userid 建立索引。而在这个 SQL 语句的第一个 LEFT JOIN ON 子句中: 



LEFT JOIN _myuser AS t3 ON t1.userid=t3.userid 

_mydata 的 userid 被参与了条件比较运算。于是我为给 _mydata 表根据字段 userid 建立了一个索引: 



mysql> ALTER TABLE `_mydata` ADD INDEX ( `userid` ) 

建立此索引之后,CPU 马上降到了 80% 左右。看到找到了问题所在,于是检查另一个反复出现在 show processlist 中的 sql 语句: 



SELECT COUNT(*) 

FROM _mydata AS t1, _mydata_key AS t2 

WHERE t1.pid=t2.pid and t2.keywords = ‘孔雀’ 

经检查 _mydata_key 表的结构,发现它只为 pid 建了了 primary key, 没有为 keywords 建立 index。_mydata_key 目前有 33 万条记录,在没有索引的情况下对33万条记录进行文本检索匹配,不耗费大量的 cpu 时间才怪。看来就是针对这个表的检索出问题了。于是同样为 _mydata_key 表根据字段 keywords 加上索引: 



mysql> ALTER TABLE `_mydata_key` ADD INDEX ( `keywords` ) 

建立此索引之后,CPU立刻降了下来,在 50%~70%之间震荡。 



再次调用 show prosslist,网站A 的sql 调用就很少出现在结果列表中了。但发现此主机运行了几个 Discuz 的论坛程序, Discuz 论坛的好几个表也存在着这个问题。于是顺手一并解决,cpu占用再次降下来了。(2007.07.09 附注:关于 discuz 论坛的具体优化过程,我后来另写了一篇文章,详见:千万级记录的 Discuz! 论坛导致 MySQL CPU 100% 的 优化笔记 http://www.xiaohui.com/dev/server/20070701-discuz-mysql-cpu-100-optimize.htm) 



解决 MYSQL CPU 占用 100% 的经验总结 



增加 tmp_table_size 值。mysql 的配置文件中,tmp_table_size 的默认大小是 32M。如果一张临时表超出该大小,MySQL产生一个 The table tbl_name is full 形式的错误,如果你做很多高级 GROUP BY 查询,增加 tmp_table_size 值。 这是 mysql 官方关于此选项的解释: 

tmp_table_size 



This variable determines the maximum size for a temporary table in memory. If the table becomes too large, a MYISAM table is created on disk. Try to avoid temporary tables by optimizing the queries where possible, but where this is not possible, try to ensure temporary tables are always stored in memory. Watching the processlist for queries with temporary tables that take too long to resolve can give you an early warning that tmp_table_size needs to be upped. Be aware that memory is also allocated per-thread. An example where upping this worked for more was a server where I upped this from 32MB (the default) to 64MB with immediate effect. The quicker resolution of queries resulted in less threads being active at any one time, with all-round benefits for the server, and available memory. 



对 WHERE, JOIN, MAX(), MIN(), ORDER BY 等子句中的条件判断中用到的字段,应该根据其建立索引 INDEX。索引被用来快速找出在一个列上用一特定值的行。没有索引,MySQL不得不首先以第一条记录开始并然后读完整个表直到它找出相关的行。表越大,花费时间越多。如果表对于查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要考虑所有数据。如果一个表有1000行,这比顺序读取至少快100倍。所有的MySQL索引(PRIMARY、UNIQUE和INDEX)在B树中存储。 



根据 mysql 的开发文档: 



索引 index 用于: 



快速找出匹配一个WHERE子句的行 

当执行联结(JOIN)时,从其他表检索行。 

对特定的索引列找出MAX()或MIN()值 

如果排序或分组在一个可用键的最左面前缀上进行(例如,ORDER BY key_part_1,key_part_2),排序或分组一个表。如果所有键值部分跟随DESC,键以倒序被读取。 



在一些情况中,一个查询能被优化来检索值,不用咨询数据文件。如果对某些表的所有使用的列是数字型的并且构成某些键的最左面前缀,为了更快,值可以从索引树被检索出来。 



假定你发出下列SELECT语句: 



mysql> SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2; 

如果一个多列索引存在于col1和col2上,适当的行可以直接被取出。如果分开的单行列索引存在于col1和col2上,优化器试图通过决定哪个索引将找到更少的行并来找出更具限制性的索引并且使用该索引取行。 

MySQL 有关“InnoDB: Error: log file ib_logfile0 is of different size 0 5242880 bytes”错误

1,查看Mysqld mysql.err 日志,发现以下错误:

150811 08:51:02 mysqld_safe Starting mysqld daemon with databases from /home/mysql/var
150811  8:51:02 [Warning] The syntax ‘–log-slow-queries’ is deprecated and will be removed in a future release. Please use ‘–slow
-query-log’/’–slow-query-log-file’ instead.
150811  8:51:02 InnoDB: The InnoDB memory heap is disabled
150811  8:51:02 InnoDB: Mutexes and rw_locks use GCC atomic builtins
150811  8:51:02 InnoDB: Compressed tables use zlib 1.2.3
150811  8:51:02 InnoDB: Initializing buffer pool, size = 256.0M
150811  8:51:02 InnoDB: Completed initialization of buffer pool
InnoDB: Error: log file /home/mysql/var/ib_logfile0 is of different size 0 5242880 bytes
InnoDB: than specified in the .cnf file 0 67108864 bytes!
150811  8:51:02 [ERROR] Plugin ‘InnoDB’ init function returned error.
150811  8:51:02 [ERROR] Plugin ‘InnoDB’ registration as a STORAGE ENGINE failed.
150811  8:51:02 [ERROR] Unknown/unsupported storage engine: InnoDB
150811  8:51:02 [ERROR] Aborting
150811  8:51:02 [Note] /usr/local/mysql/bin/mysqld: Shutdown complete
150811 08:51:02 mysqld_safe mysqld from pid file /home/mysql/var/centos.pid ended

2,解决办法

If you want to change the number or the size of your InnoDB log files, you
have to shut down MySQL and make sure that it shuts down without errors.
Then copy the old log files into a safe place just in case something went
wrong in the shutdown and you will need them to recover the database. Delete
then the old log files from the log file directory, edit my.cnf, and start
MySQL again. InnoDB will tell you at the startup that it is creating new log
files.

在你修改my.cnf的innodb_log_file_size参数前,请先停止mysql服务程序的运行(mysql的停止没有出现任何错误),并把/var/lib/mysql目录下的ib_logfile0、ib_logfile1、ib_logfile2等之类的文件移除到一个安全的地方(旧日志文件的保留是为了防止意外的出现),以便Mysql重启后可以将新的ib_logfile0之类日志文件生成到/var/lib/mysql目录下。如果没有什么意外,旧的日志文件可以删除。

让history显示详细执行时间,及linux历史命令使用技巧

history命令主要用于显示历史指令记录内容和曾经执行过的指令 。经常使用Linux命令会有助于提升你的工作效率。

当一台服务器有多人管理时,可能会出现一些误操作或者重复操作,出现问题的时侯要查询什么时间执行什么命令,由于Linux默认的history记录仅保存了命令的内容,没有具体的时间,因此,我们有必要对history历史命令的记录功能进行优化,具体分为设置保存历史命令history的文件大小,保存历史命令history的条数,保存每条历史命令history的执行时间,方法如下:

[fcbu.com@localhost ~]# vi /etc/bashrc

#未尾添加如下信息

# 设置保存历史命令的文件大小

export HISTFILESIZE=500000000

# 保存历史命令条数

export HISTSIZE=1000000

# 实时记录历史命令,默认只有在用户退出之后才会统一记录,很容易造成多个用户间的相互覆盖。

export PROMPT_COMMAND=”history -a”

# 记录每条历史命令的执行时间

export HISTTIMEFORMAT=”%Y/%m/%d %H:%M:%S ”

使更改立即生效

# source /etc/bashrc

linux历史命令使用技巧

列出所有的历史记录:

[fcbu.com@localhost ~]# history

只列出最近10条记录:

[fcbu.com@localhost ~]# history 10 (注,history和10中间有空格)

使用命令记录号码执行命令,执行历史清单中的第99条命令

[fcbu.com@localhost ~]#!99 (!和99中间没有空格)

重复执行上一个命令

[fcbu.com@localhost ~]#!!

执行最后一次以rpm开头的命令(!?  ?代表的是字符串,这个String可以随便输,Shell会从最后一条历史命令向前搜索,最先匹配的一条命令将会得到执行。)

[fcbu.com@localhost ~]#!rpm

逐屏列出所有的历史记录:

[fcbu.com@localhost ~]# history | more

立即清空history当前所有历史命令的记录

[fcbu.com@localhost ~]#history -c

通过指定关键字来执行以前的命令

在下面的例子,输入 !ps 并回车,将执行以 ps 打头的命令

history命令的用途确实很大!但需要小心安全的问题!尤其是 root 的历史纪录档案,这是黑客们的最爱!因为不小心的 root 会将很多的重要资料在执行的过程中会被纪录在 ~/.bash_history 当中,如果这个档案被解析的话,后果不堪设想!

使用 HISTFILE 更改历史文件名称

默认情况下,命令历史存储在 ~/.bash_history 文件中。添加下列内容到 .bash_profile 文件并重新登录 bash shell,将使用 .commandline_warrior 来存储命令历史:

[fcbu.com@localhost ~]# vi ~/.bash_profile

HISTFILE=/root/.commandline_log

使用 -c 选项清除所有的命令历史,如果你想清除所有的命令历史,可以执行:

[fcbu.com@localhost ~]# history -c

低延时直播应用

直播应用中,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简单多了。

互联网视频的实际工业标准RTMP: 有多少个坑?

最简单的PC流媒体应用,可以使用Flash采集摄像头和麦克风后,以RTMP协议推送给流媒体服务器,然后在浏览器中用Flash播放器播放这个RTMP流。总共需要多少行代码?可以100行as代码就可以实现,脏累烦的事情都是flash搞定了。

视频点播,从来就不是RTMP的事情,那是HTTP文件的世界,一个HTTP-MP4文件,可以在所有平台观看。直播呢也不仅仅是PC了,移动互联网、h.265和mpeg-dash,这些视频的新技术,发展的速度非常快。而HLS这个和RTMP一样古老的Apple的流媒体技术,在Android3支持了HLS后,HLS成了移动互联网应用最广泛的技术。

RTMP还是那个RTMP,从视频的编码采集到服务器,还是RTMP;分发到PC,可以RTMP,也可以HLS了;分发到移动互联网,自己的app可以RTMP,浏览器只能HLS了。

而流媒体服务器的角色,也从分发RTMP直播流,变成了分发RTMP和HLS流。RTMP对于直播流媒体服务器,还是扰不过去的大坑。让我们一起数一数RTMP这个坑里有多少个球吧。

第一个球,变更过的加密握手协议。RTMP协议Adobe公开了吗?是的,可以在Adobe官网上下载。按照协议实现一个RTMP服务器时,发现里面的握手是变更过了的;这就是为何SRS需要编译openssl库,需要从客户端的握手信息中获取客户端的公钥,然后按照指定算法交换密钥。如果按照RTMP标准文档握手会怎样?Flash播放器只能播放vp6编码的流,无法播放h.264的流,呵呵。

第二个球,变更过的扩展时间戳传输方法。RTMP的时间戳是24位的,如果超过这个4.5小时连续推流,就需要用到高8位的扩展时间戳。标准中说,chunked的X3包,是不能包含扩展时间戳的;可惜Adobe的所有产品都用了,从flash到FMLE到FMS。而ffmpeg中也有注释抱怨说Adobe太坑爹了,没事改它干啥。而SRS中对于这种处理,是采用猜测,即X3的chunked包先读4字节出来,如果和消息的时间戳吻合那么就是Adobe系统,也有些开源的产品遵守规范的,SRS会自动适配。

第三个球,RTMP的时间戳是32位还是31位?在flv标准中,明确讲了是31位(SI32)即24.8天左,而按照RTMP的49.7天回绕的说法应该是32位。一般没有问题,谁会看一个直播24.8天呢?额,这个不是很严谨的做法,对于服务器来讲。SRS使用31位。

第四个球,不能变更ChunkSize。有些服务器不能变更ChunkSize,所以SRS在Edge模式时,回源某些服务器会有问题。这个球只能配置SRS的默认ChunkSize,配置为128即原始值。

第五个球,溢出的ChunkSize。RTMP标准说ChunkSize最大不超过65535,有个什么球服务器,就喜欢设置一个比这个大得多的ChunkSize,泥马!这个该怎么处理?忽略标准就好,实际上没有这个上限。

RTMP的扩展时间戳传输,请参考:http://blog.csdn.net/win_lin/article/details/13363699

RTMP的复杂握手协议,请参考:https://github.com/winlinvip/simple-rtmp-server/wiki/v1_CN_RTMPHandshake

RTMP的更多信息,请参考:https://github.com/winlinvip/simple-rtmp-server/wiki/v1_CN_DeliveryRTMP

用nginx-rtmp的63%代码,增加80%的功能,SRS用到的ST是个什么球?

这次我要讲的是:ST(state-threads)是个什么球?

趁着吃完饭休息会儿,给大家讲讲ST(state-threads),一个四两拨千斤的想法。基于ST的SRS1只用了4.3万行(63%)代码,比nginx-rtmp多了83%的功能,周期缩短100%;而SRS2只用了6.5万行(95%)代码,比nginx-rtmp多了230%功能。开发周期SRS1用了1年,SRS2用了1年;nginx-rtmp发布1.0用了2年。啥都不说了,SRS3就不再和nginx-rtmp比了,SRS3和SRS2比吧~

如果说代码行数不能说明问题,那再爆料一组数据,SRS1的注释率是22.1%,而SRS2的注释率是23.7,nginx-rtmp注释率是3%。可见SRS用ST简化了多少逻辑。nginx-rtmp的6.8万行代码,是去掉了其他模块,只有core和rtmp等必要模块,总共nginx-rtmp有16万行代码。

ST解决的是服务器的最根本问题:如何以最高效率服务多个客户端连接?答案就是nginx的架构,即单线程异步非阻塞socket(没错还有多进程,我们先只考虑如何一个进程最高效);在linux中,就是epoll+send(MSG_DONTWAIT),具体的可以翻翻书柜,epoll早就不是什么新鲜事了。

这个架构可以打个比方,一个快递员在送快递时,假设有4个客户分别在四个完全不同的方向,东家西家南家北家,快递员每家都要送1000个包裹,快递员的货车有限先送东家1000个包裹,东家收了100个候发现家里没有空间了得腾缓冲区出来,快递员只好暂时不管东家了(非阻塞啦),去给西家送了200个还有800个,南家300个还有700个,北家1个还有999个。

接下来肿么办?最快的方式当然是各家的空间腾出来后,快递员用epoll_wait就知道哪些可以继续了,这就是异步啦。这个异步非阻塞是相当高的效率,但是麻烦的地方在于,快递员每次都要登记各家的状态,然后跑到各家去继续送(调用不同的处理函数),路上不仅浪费很多时间,而且维护这些信息非常之麻烦啊!每次都得把路重新计算规划,再跑一边非常需要费脑筋啦。

最简单的方式是不要登记各家状态,每家都派一个快递员啦(创建线程),各家有空间这个快递员马上就继续发,这样是最简单的逻辑;缺点是要做线程同步咯,而且很昂贵啦,没法一下子服务几万个用户。

孙悟空的毫毛可以用在这里,分身术,实际上还是一个快递员,但是在各家那里分个身。好处是不用登记那些信息,各家有空间了立马就开始写;比线程的优势是不用锁,开销小。ST就是分身术,虚拟线程,即用户空间线程协程,类似goroutine,或者C#的纤程。

协程完全是不同于进程和线程的一套写代码思路,解决问题的思路不一样,当然结果是不一样的啦。在处理rtmp的edge,以及http-flv的hstrs(http stream trigger rtmp source)时,涉及到多个线程交互,这种就相当于两个异步状态空间相乘,那个是相当之复杂的。这是为何nginx-rtmp实现RTMP比较费劲,要实现RTMP-EDGE,以及HTTP-FLV、HSTRS是非常难的事情。

关于ST更多信息,请参考:http://blog.csdn.net/win_lin/article/details/8242653