🔗 缓存 YouTube 内容
squid-users 邮件列表。
此页面仍在开发中。这不仅是因为它必须跟上 youtube.com 的更改。如果您开始遇到这些配置的任何问题,请先回到此处查看更新后的配置。
![]()
![]()
Google/YouTube 更改了他们的系统以提高安全性,因此本文档的当前状态不再适用。您需要使用内容适应来实现 YouTube 缓存,这并非初学者任务。
🔗 目录
squid 3.1 之前的默认配置会阻止缓存 动态内容,而 youtube.com 专门实现了一些“功能”来阻止其 Flash 视频被缓存有效地分发。
本文档详细介绍了公开可用的策略,用于克服其中至少一些问题,并允许缓存大量的 youtube.com 内容。请注意,此演示配置的成功率参差不齐,对某些人有效,但其他人报告它完全无效。
每个配置操作都详细说明了其原因和效果,因此如果您发现有错误或遗漏,请告知我们。
🔗 部分解决方案 1:本地 Web 服务器
此方案有一个更完善、更成熟且更昂贵的商业版本,名为 VideoCache。
*by JoshuaOSullivan*
幸运的是,通过一些“脏”代码,我设法让 YouTube 缓存工作了。
我的方法需要一个基本正常的 squid 设置,外加一个 URL 重写脚本,该脚本会将所有发往 YouTube 的请求重定向到一个特殊的缓存 Web 服务器脚本,即,http://www.youtube.com/watch?v=avaSdC0QOUM 会被改写成 http://10.13.37.25/per.php?url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DavaSdC0QOUM%0A
该脚本会检查 URL,使用 readfile() 将它们全部传递,除了那些我们想要保留的 .flv 文件。当遇到这些 .flv URL 时,会使用 fopen() 来查找视频大小,并解析 URL 以找到视频的 ID。对于相同分辨率的相同视频,这些似乎是恒定的。会生成一个名为“id-size”的文件名。这是我使用的文件命名格式,它允许区分相同来源但不同分辨率的视频,并确保缓存中的视频不会损坏(正确的大小 -> 事情很可能没问题)。
一旦生成此文件名,就会搜索缓存文件夹,如果找到,则将文件交付给用户。然后关闭与 YouTube 的连接,不再下载任何数据(除了包含文件信息的头部)。如果文件夹中未找到文件名,则视频会分块下载(在 while 循环中使用 fread()),并交付给用户,同时保存到文件中。
此解决方案的优点
- 适用于任何 Squid 版本
- 易于适应其他 CDN
缺点
- 截至目前,用户无法登录,因为我尚未在脚本中实现传递 POST 数据。我已告知用户我不在乎,但你可能在乎。
- 如果两个人同时观看一个未缓存的视频,则两者都会下载。
- 需要始终运行一个 Web 服务器
- Squid 将不会持有文件,您的 Web 服务器将不得不持有它们(并以其他方式管理缓存大小)
我的解释可能不完整,如有任何疑问,请发送电子邮件至 osullijosh <at> ecs.vuw.ac.nz。
🔗 squid.conf 配置
# determine which URLs are going to be caught
acl youtube dstdomain .youtube.com
# pass requests
url_rewrite_program /etc/squid/phpredir.php
url_rewrite_access allow youtube
# leave caching up to the local web server
cache deny youtube
/usr/bin/php 可能不是您系统中 PHP 的正确路径或名称。请务必检查并根据需要更新以下示例。
另外,请注意移除 # ! 之间的空格。那里是为了避免 wiki 的 bug。
phpredir.php
# !/usr/bin/php
<?php
while ( $input = fgets(STDIN) ) {
// Split the output (space delimited) from squid into an array.
$input=explode(" ",$input);
if(preg_match("@youtube@",$input[0])){
$input[0]=urlencode($input[0]);
$input= implode(" ",$input);
echo "http://10.13.37.25/per.php?url=$input"; //URL of my web server
}else
echo ""; // empty line means no re-write by Squid.
}
?>
per.php
<?php
$file_path="/var/www/videos";
$logfile="$file_path/cache.log";
$url=urldecode($_GET['url']);
$urlptr=fopen($_GET['url'],"r");
$blocksize=32*1024;
//attempt to get. a 404 shouldn't happen, but...
if($urlptr===FALSE){
header("Status: 404 Not Found");
die();
}
//find content type and length
foreach($http_response_header as $line){
if(substr_compare($line,'Content-Type',0,12,true)==0)
$content_type=$line;
else if(substr_compare($line,'Content-Length',0,14,true)==0){
$content_length=$line;
}
}
/**Youtube will detect if requests are coming form the wrong ip (ie, if only video requests are redirected, so, we must redirect all requests to youtube.
As such, we must capture all requests t youtube. Most are unimportant, so we can pass them straight through **/
if(!preg_match("@.*youtube.*videoplayback.*@",$url)){
fpassthru($urlptr);
fclose($urlptr);
exit(0);
}
//send content type and length
header($content_type);
header($content_length);
//find youtube id;
$url_exploded=explode('&',$url);
$id="";
foreach($url_exploded as $line){
if(substr($line,0,3)==='id=')
$id=substr($line,3);
}
//Get the supposed file size
$length=intval(substr($content_length,16));
file_put_contents($logfile,"\nFound id=$id, content-type: $content_type content-length=$content_length\n",FILE_APPEND);
//Do we have it? delivar if we do
$fname="$file_path/$id-$length";
//Check if we have the file, and it is the correct size. incorrect size implies corruption
if(file_exists($fname) &&filesize($fname)==$length){
readfile($fname);
logdata("HIT",$url,$fname);
exit(0);
}
//file not in cache? Get it, send it & save it
logdata("MISS",$url,$fname);
$fileptr=fopen($fname,"w");
//no validity check, simply don't write the file if we can't open it. prevents noticeable failure/
while(!feof($urlptr)){
$line=fread($urlptr,$blocksize);
echo $line;
if($fileptr) fwrite($fileptr,$line);
}
fclose($urlptr);
if($fileptr) fclose($fileptr);
function logdata($type,$what, $fname){
$file_path="/var/www/videos";
$logfile="$file_path/cache.log";
$line="@ ".time()."Cache $type url: $what file: $fname client:".$_SERVER['REMOTE_ADDR']."\n";
file_put_contents($logfile,$line,FILE_APPEND);
}
?>
🔗 部分解决方案 2:Squid 存储去重
一些对 squid 的私有修改似乎已经实现了 youtube.com 的缓存。但是,目前没有简单的解决方案可供公众使用。
要缓存 youtube.com 文件,您需要启用对 动态内容 的缓存。此外还需要一些其他措施,这些措施在技术上违反了 HTTP 标准。
***安全说明:*** 一些必需的配置(quick_abort_min + large maximum_object_size)需要折叠转发功能来防止高带宽消耗和可能的缓存 DDoS 攻击。Squid-3 目前不具备此功能。建议使用 Squid-2.7 来配合这些设置。
如果您需要 Squid-3 的功能,可以通过将 Squid-2.7 代理配置为专门用于缓存和提供媒体内容的 cache_peer 来实现此功能。
🔗 缺失的部分
此配置仍不完整,youtube.com 的某些行为是 squid 目前无法自行处理的。因此,私有端口是变体,而不是配置。
- 来自 youtube.com 的每个视频请求都包含一个非随机但变化的参数,紧邻视频名称。Squid 目前无法仅为哈希保留查询字符串的 *一部分*。开箱即用的规则是全有或全无。
- youtube.com 的负载均衡方法使用了许多变化的子域。同样,任何给定的视频似乎都可以从这些子域中的一个或多个处获得。同样,squid 在其 URI 哈希方面也是全有或全无的。
解决这两个问题的组合方法是为 squid 添加一项功能,用于检测相同的内容和不同的 URL。可能通过 ACL 限制为某个站点范围等。任何人能够捐赠时间和/或金钱来完成这项工作都会受到许多人的喜爱。
更新:请参阅 Squid-2.7 中 storeurl_rewrite_program 功能。
🔗 Squid 配置文件
# REMOVE these lines from squid.conf
acl QUERY urlpath_regex cgi-bin \?
cache deny QUERY
# Break HTTP standard for flash videos. Keep them in cache even if asked not to.
refresh_pattern -i \.flv$ 10080 90% 999999 ignore-no-cache override-expire ignore-private
# Apparently youtube.com use 'Range' requests
# - not seen, but presumably when a video is stopped for a long while then resumed, (or fast-forwarded).
# - convert range requests into a full-file request, so squid can cache it
# NP: BUT slows down their _first_ load time.
quick_abort_min -1 KB
# Also videos are LARGE; make sure you aren't killing them as 'too big to save'
# - squid defaults to 4MB, which is too small for videos and even some sound files
maximum_object_size 4 GB
# Let the clients favorite video site through with full caching
# - they can come from any of a number of youtube.com subdomains.
# - this is NOT ideal, the 'merging' of identical content is really needed here
acl youtube dstdomain .youtube.com
cache allow youtube
# kept to demonstrate that the refresh_patterns involved above go before this.
# You may be missing the CGI pattern, it will need to be added if so.
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern . 0 0% 4320
🔗 另请参阅
⚠️ Disclaimer: Any example presented here is provided "as-is" with no support
or guarantee of suitability. If you have any further questions about
these examples please email the squid-users mailing list.
类别: ConfigExample
导航:网站搜索,网站页面,类别,🔼 向上