跳到内容

在后台解析缓存图片

编辑此页

默认情况下,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
这项工作,包括代码示例,均根据 Creative Commons BY-SA 3.0 许可获得许可。
目录
    版本