Emi*_*oni 4 php image server-load
我正在构建一个基于Web的系统,它将承载高负荷图像的负载和负载,并且它们将可供出售.当然我永远不会显示高分辨率图像,而是在浏览时人们只能看到低分辨率的水印图像.目前的工作流程如下:
PHP脚本处理高图像上传,当图像上传时,它会自动调整为低分辨率图像和缩略图图像,并且两个文件都保存在服务器上(不添加水印).
当人们浏览时,页面显示图像的缩略图,点击时,它会放大并显示带有水印的低图像.目前,每当打开低位图像时,我都会动态应用水印.
我的问题是,正确的方法是什么:
1)我是否应该使用缩略图保存低级图像的第二个副本,只有在第一次访问时?我的意思是如果有人访问图像,我会动态添加水印,然后显示图像并将其存储在服务器上.如果存在水印副本,则下次访问相同图像时只显示wm副本,否则即时应用水印.(如果更改了watermark.png,只需删除带水印的图像,它们将被重新创建为已访问).
2)我应该像现在一样继续使用水印.
我最大的问题是PHP之间的差异有多大file_exists()
,并且为图像添加水印,例如:
$image = new Imagick();
$image->readImage($workfolder.$event . DIRECTORY_SEPARATOR . $cat . DIRECTORY_SEPARATOR .$mit);
$watermark = new Imagick();
$watermark->readImage($workfolder.$event . DIRECTORY_SEPARATOR . "hires" . DIRECTORY_SEPARATOR ."WATERMARK.PNG");
$image->compositeImage($watermark, imagick::COMPOSITE_OVER, 0, 0);
Run Code Online (Sandbox Code Playgroud)
所有低图像都是1024x1024,JPG,质量设置为45%,并且删除了所有不必要的滤镜,因此低图像的文件大小约为40Kb-80Kb.
它在某种程度上与这个问题有关,只是规模和情景有点不同.
我在专用服务器(Xeon E3-1245v2)cpu,32 GB RAM,2 TB存储),该网站整体流量不大,但它不时有巨大的峰值.当图像发布时,我们每小时可以获得几千次点击,人们可以通过图像浏览,下载,购买等等.因此,在正常使用情况下,我确信即时生成是正确的方法,我有点担心关于穗期.
需要提一下,我正在使用ImageMagick库进行图像处理,而不是GD.
感谢您的输入.
UPDATE
没有一个完整的完整解决方案的答案,但这是好的,因为我从来没有寻找过.这是一个艰难的决定,哪一个接受谁和谁给予赏金.
@ Ambroise-Maupate解决方案很好,但它继续在PHP上完成这项工作.
@Hugo Delsing建议使用Web服务器来提供缓存文件,降低对PHP脚本的调用,这意味着使用更少的资源,另一方面,它不是真正的存储友好.
我将使用2个答案的混合合并解决方案,转发CRON作业以删除垃圾.
谢谢你的指示.
小智 5
我建议你在飞行中创建水印图像,并在每个人建议的同时缓存它们.
然后你可以创建一个垃圾收集器 PHP脚本,每天都会执行(使用cron).此脚本将浏览您的缓存文件夹以读取每个图像访问时间.这可以使用fileatime()
PHP方法完成.然后,当在24或48小时内未访问缓存的wm图像时,只需将其删除即可.
使用此方法,您可以处理峰值周期,因为图像在第一次请求时被缓存.并且您将节省您的硬盘空间,因为您的垃圾收集器脚本将为您删除未使用的图像.
仅当您的服务器分区启用了atime更新时,此方法才有效.
见http://php.net/manual/en/function.fileatime.php
我个人将以CDN类创建静态/无cookie子域来处理此类图像。主要原因是:
第一步是在一个指向空文件夹的子域上创建一个网站。使用IIS / Apache的设置或禁用此新网站的会话的设置。还要在网站上设置一些长缓存标题,因为内容不应更改
第二步是创建一个.htaccess
包含以下内容的文件。
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*) /create.php?path=$1 [L]
Run Code Online (Sandbox Code Playgroud)
这将确保如果有人访问现有图像,它将直接显示图像而不会产生PHP
干扰。每个不存在的请求都将由create.php
脚本处理,这是您应该添加的下一件事。
<?php
function NotFound()
{
if (!headers_sent()) {
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
header($protocol . ' 404 Not Found');
echo '<h1>Not Found</h1>';
exit;
}
}
$p = $_GET['path'];
//has path
if (strlen($p)<=1)
NotFound();
$clean = explode('?', $p);
$clean = explode('#', $clean[0]);
$params = explode('/', substr($clean[0], 1)); //drop first /
//I use a check for two, because I dont allow images in the root folder
//I also use the path to determine how it should look
//EG: thumb/125/90/imagecode.jpg
if (count($params)<2)
NotFound();
$type = $params[0];
//I use the type to handle different methods. For this example I only used the full sized image
//You could use the same to handle thumbnails or cropped/watermarked
switch ($type) {
//case "crop":if (Crop($params)) return; else break;
//case "thumb":if (Thumb($params)) return; else break;
case "image":if (Image($params)) return; else break;
}
NotFound();
?>
<?php
/*
Just some example to show how you could create a responds
Since you already know how to create thumbs, I'm not going into details
Array
(
[0] => image
[1] => imagecode.JPG
)
*/
function Image($params) {
$tmp = explode('.', $params[1]);
if (count($tmp)!=2)
return false;
$code = $tmp[0];
//WARNING!! SQL INJECTION
//USE PROPER DB METHODS TO GET REALPATH, THIS IS JUST EXAMPLE
$query = "SELECT realpath FROM images WHERE Code='".$code."'";
//exec query here to $row
$realpath = $row['realpath'];
$f = file_get_contents($realpath);
if (strlen($f)<=0)
return false;
//create folder structure
@mkdir($params[0]);
//if you had more folders, continue creating the structure
//@mkdir($params[0].'/'.$params[1]);
//store the image, so a second request won't access this script
file_put_contents($params[0].'/'.$params[1], $f);
//you could directly optimize the image for web to make it even better
//optimizeImage($params[0].'/'.$params[1]);
//now serve the file to the browser, because even the first request needs to show the image
$finfo = finfo_open(FILEINFO_MIME_TYPE);
header('Content-Type: '.finfo_file($finfo, $params[0].'/'.$params[1]));
echo $f;
return true;
}
?>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1163 次 |
最近记录: |