在后台解析缓存图片
默认情况下,LiipImagineBundle 会按需处理图像。当请求的图像尚未通过请求的过滤器集进行缓存时,控制器会应用过滤器并缓存结果。然后,它会将客户端重定向到生成的图像文件。
这无需任何其他工具即可工作。但是,也存在一些重要的缺点:
- 对图像应用所有过滤器可能需要大量时间和内存;
- 图像必须由响应 Web 请求的 Web 服务器处理。这会增加服务器的负载,并可能影响性能;
- 解析控制器 URL 与缓存的图像 URL 不同。当需要生成图像时,缓存的 HTML 页面包含指向控制器的 URL。如果您正在缓存 HTML,则所有使用缓存的客户端都会被发送到控制器,并且需要经历重定向,即使这是不必要的。
为了提前准备缓存的图像,LiipImagineBundle 允许您使用消息队列来运行 worker,以异步预热缓存。您的应用程序必须在意识到图像时(文件上传、导入过程等)发送有关图像的消息,并且您需要为消息队列运行 worker。
Symfony Messenger
此 bundle 提供了与 Symfony Messenger 的集成。启用后,它提供了一个消息处理程序来消费预热消息。
步骤 1:安装
首先,使用 composer 安装 symfony/messenger
1
composer require symfony/messenger
1 2 3 4 5 6 7 8 9 10 11 12
# config/packages/messenger.yaml
framework:
messenger:
transports:
# https://symfony.ac.cn/doc/current/messenger.html#transport-configuration
liip_imagine: '%env(MESSENGER_TRANSPORT_DSN)%'
sync: 'sync://'
routing:
# Route your messages to the transports
'Liip\ImagineBundle\Message\WarmupCache': liip_imagine
步骤 2:配置 LiipImagineBundle
我们需要指示 LiipImagineBundle 加载消息处理程序,该处理程序消费预热消息并在与 Web 请求无关的单独进程中准备缓存的图像。
1 2 3 4
# config/packages/liip_imagine.yaml
liip_imagine:
messenger: true
步骤 3:运行消费者
我们需要为消息运行至少一个消费者
1
php bin/console messenger:consume liip_imagine --time-limit=3600 --memory-limit=256M
您可以在单独的机器上运行消费者,只要它与缓存图像共享相同的存储即可。在云系统中,您甚至可以根据队列大小扩展消费者,以获得快速处理,而无需占用在大多数时间里无所事事的资源。
步骤 4:发送 WarmupCache 消息
最后一步是让消息消费者知道它需要缓存的图像。当我们在 Twig 模板中引用图像时,使用消息系统为时已晚。
使用原始图像路径(就像在 Twig 中使用它一样)分发消息。您可以指定要预热的过滤器集,也可以将其省略,让消息消费者预热所有可用的过滤器集。
默认情况下,现有缓存的图像不会被替换。您可以强制重新创建缓存。如果设置了 force
,则会重新创建缓存的图像。如果您用与之前具有相同文件名的新版本替换图像,则强制重新创建非常有用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
<?php
use Liip\ImagineBundle\Message\WarmupCache;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Messenger\MessageBusInterface;
class DefaultController extends AbstractController
{
public function index(MessageBusInterface $messageBus)
{
// warmup all caches
$messageBus->dispatch(new WarmupCache('the/path/img.png'));
// warmup specific cache
$messageBus->dispatch(new WarmupCache('the/path/img.png', ['fooFilter']));
// force warmup (removes the cache if exists)
$messageBus->dispatch(new WarmupCache('the/path/img.png', null, true));
}
}
Enqueue (已弃用)
enqueue 库集成已弃用,建议使用 Symfony Messenger 集成。
Enqueue 集成将在下一个主要版本中删除。
步骤 1:安装 EnqueueBundle
首先,我们必须安装 EnqueueBundle。您基本上必须使用 composer 安装 bundle,将其注册到 AppKernel 并调整设置。这是没有任何额外依赖项的最小配置。它基于 filesystem transport。
1 2 3 4 5 6
# app/config/config.yml
enqueue:
default:
transport: 'file://%kernel.root_dir%/../var/queues'
client: ~
步骤 2:配置 LiipImagineBundle
在此步骤中,我们指示 LiipImagineBundle 加载一些在后台处理图像所需的额外内容。
1 2 3 4
# app/config/config.yml
liip_imagine:
enqueue: true
步骤 3:运行消费者
在我们开始使用它之前,我们需要一个消费者池(至少一个)在后台工作。以下是如何运行它:
1
./bin/console enqueue:consume --setup-broker -vvv
步骤 4:发送解析缓存消息
您必须发送消息才能在后台处理图像。消息必须包含原始图像路径(在 LiipImagineBundle 的术语中)。如果您未定义过滤器,则后台进程将解析所有可用过滤器的缓存。如果缓存已存在,则默认情况下后台进程不会重新创建它。您可以强制重新创建缓存,在这种情况下,缓存的图像将被删除,并替换为新图像。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
<?php
use Enqueue\Client\ProducerInterface;
use Liip\ImagineBundle\Async\Commands;
use Liip\ImagineBundle\Async\ResolveCache;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* @var ContainerInterface $container
* @var ProducerInterface $producer
*/
$producer = $container->get(ProducerInterface::class);
// resolve all caches
$producer->sendCommand(Commands::RESOLVE_CACHE, new ResolveCache('the/path/img.png'));
// resolve specific cache
$producer->sendCommand(Commands::RESOLVE_CACHE, new ResolveCache('the/path/img.png', array('fooFilter')));
// force resolve (removes the cache if exists)
$producer->sendCommand(Commands::RESOLVE_CACHE, new ResolveCache('the/path/img.png', null, true));
// send command and wait for reply
$reply = $producer->sendCommand(Commands::RESOLVE_CACHE, new ResolveCache('the/path/img.png', null, true), true);
$replyMessage = $reply->receive(20000); // wait for 20 sec