Статьи

Хет-трик кэширования: библиотеки Varnish, Memcached и PHP

Ранее мы рассмотрели некоторые распространенные механизмы кэширования, которые можно легко использовать для ускорения работы наших приложений. В этой части мы рассмотрим некоторые дополнительные программы, которые мы можем использовать с PHP для кэширования.

Abstract image with text cache

Memcached

Memcached — это хранилище значений ключей в памяти. Вы можете использовать его для хранения таких вещей, как строки, числовые значения, объекты и массивы.

Установка Memcached

Вы можете выполнить команду ниже, чтобы установить memcached в Ubuntu или другой ОС на основе Debian:

sudo apt-get install memcached 

Чтобы он работал с PHP, вам также необходимо установить расширение PHP:

 sudo apt-get install php5-memcached 

Чтобы проверить, работает ли memcached, найдите ‘memcached’ в выводе, возвращаемом при вызове phpinfo() со страницы. Вы должны увидеть что-то похожее на следующее:

memcached

Использование Memcached

Чтобы использовать memcached, сначала мы создаем новый экземпляр класса Memcached . Затем мы указываем, к какому серверу мы хотим подключиться, вызывая метод addServer . $memcached_host — это IP-адрес или доменное имя сервера, а $memcached_port — это порт, на котором работает сервер memcached. По умолчанию это 11211.

 $mem = new Memcached(); $memcached_host = '127.0.0.1'; $memcached_port = 11211; $mem->addServer($memcached_host, $memcached_port); 

Как только это будет сделано, вы можете использовать метод set для кэширования определенной пары ключ-значение. Метод set принимает уникальный ключ в качестве первого аргумента и данные, которые вы хотите кэшировать, в качестве второго, а третий — продолжительность времени жизни данных в секундах:

 $id = 23; $my_data = array('name' => 'gon', 'occupation' => 'hunter'); $ttl = 60; $mem->set($id, $my_data, $ttl); 

Если вы хотите получить данные обратно, вы можете использовать метод get . Просто используйте уникальный ключ в качестве запроса:

 $my_data = $mem->get(23); if($my_data){ return $my_data; }else{ //fetch data from database } 

Для дальнейшей оптимизации memcached вы можете настроить его параметры. Вы можете сделать это, отредактировав файл конфигурации memcached: /etc/memcached.conf .

Вот некоторые из вариантов, которые вы можете найти полезными. Просто раскомментируйте их или отредактируйте существующие значения:

-v — если вы хотите показать больше информации во время работы memcached.
-vv — если вы не можете найти то, что ищете в подробном режиме, вы можете увидеть еще больше информации, когда вы установите эту опцию. Очень полезно при отладке.
-m — максимальный объем памяти, который может использовать memcached. По умолчанию установлено 64 МБ.
-M — сообщает memcached для возврата ошибки, когда максимальный объем памяти уже исчерпан. По умолчанию эта опция не установлена. Вместо этого он автоматически удаляет элементы из кэша.
-c — максимально допустимое количество одновременных подключений. По умолчанию это 1024.

Вы также можете установить phpMemcachedAdmin на свой memcached сервер. Он покажет вам такие вещи, как общее количество текущих подключений, ошибок подключения, текущие элементы, общий объем используемой памяти и другие данные, которые могут оказаться полезными. Вот скриншот:

phpmemcachedadmin

лакировка

Varnish — это программа, которая работает перед веб-сервером и ускоряет работу веб-приложений. Это означает, что когда пользователь заходит на ваш сайт, Varnish получает первоначальный запрос вместо веб-сервера. Если запрашиваемый контент уже существует в кэше, Varnish получает его из кэша и обслуживает его. Если он не существует, он просит веб-сервер обслужить его, помещает ответ в кэш, а затем отправляет его пользователю. В следующий раз, когда запрашивается та же страница, она извлечет ее из кэша.

Установка лака

Чтобы установить Varnish, вы должны сначала добавить репозиторий в ваши источники:

 sudo curl http://repo.varnish-cache.org/debian/GPG-key.txt | sudo apt-key add - 

Затем выполните следующее, чтобы установить Varnish:

 sudo apt-get update sudo apt-get install varnish 

Конфигурирование лака

Далее вам нужно настроить Varnish на основе вашего веб-сервера. В этом уроке я предполагаю, что веб-сервером является Apache. Начните с открытия файла конфигурации Varnish в /etc/default/varnish .

Ищите «DAEMON_OPTS», без комментариев. Убедитесь, что это так же, как показано ниже:

 DAEMON_OPTS="-a :80 \ -T localhost:6082 \ -f /etc/varnish/default.vcl \ -S /etc/varnish/secret \ -s malloc,256m" 

Вот разбивка опций, которые мы использовали выше:

  • -a — это адрес и порт Varnish слушает. В конфигурации выше мы не указали адрес. Это означает, что Varnish будет прослушивать запросы на том же сервере, где установлен веб-сервер. Обычно вам нужно установить Varnish на другой сервер, чтобы он не подвергался такой же нагрузке, как веб-сервер.
  • -T — адрес и порт, который прослушивает интерфейс управления.
  • -f — позволяет указать собственный файл конфигурации VCL вместо файла по умолчанию.
  • S — путь к файлу, содержащему секрет, используемый для авторизации доступа к порту управления.
  • -s — используется для указания серверной части хранилища. Вы можете использовать любой из вариантов на этой странице . Обычно это malloc , который использует память в качестве кеша. Это запрашивает максимальный объем памяти, который будет указан. В этом случае это 256m что составляет 256 МБ.

Далее нам нужно отредактировать файл конфигурации Varnish VCL ( /etc/varnish/default.vcl ). Это позволяет нам установить сервер, который будет служить источником.

В этом случае мы используем Apache на той же машине, где установлен Varnish, поэтому мы можем установить для хоста localhost и для порта 8888 .

 backend default { .host = "localhost"; .port = "8888"; } 

По умолчанию Apache работает на порте 80. Ранее мы настраивали Varnish для прослушивания порта 80, поэтому нам нужно заменить Apache 80 на что-то другое, иначе возникнет конфликт между Apache и Varnish.

Мы обновляем конфигурацию Apache: /etc/apache2/sites-enabled/000-default.conf .
Мы уверены, что виртуальный хост теперь настроен на порт 8888.

 <VirtualHost 127.0.0.1:8888> 

Затем мы также должны обновить файл конфигурации портов: /etc/apache2/ports.conf

Мы уверены, что у него есть определение виртуального хоста с использованием того же хоста и порта, которые используются в файле конфигурации Apache:

 Listen 127.0.0.1:8888 

Затем мы перезапускаем Apache, чтобы изменения вступили в силу.

 sudo service apache2 restart 

Используя Лак

После этого Varnish теперь готов кешировать. Давайте попробуем, создав новый файл PHP, который покажет нам некоторые новости из базы данных. Если вы хотите следовать, используйте этот github gist для получения данных. Ниже вы найдете файл PHP, который мы будем использовать для тестирования. Он выбирает title и url статьи из таблицы новостей и выводит их в виде таблицы:

 <?php $db = new Mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); $results = $db->query("SELECT title, url FROM news"); ?> <table border="1"> <thead> <tr> <th>title</th> <th>url</th> </tr> </thead> <tbody> <?php while($row = $results->fetch_object()){ ?> <tr> <td><?php echo $row->title; ?></td> <td><?php echo $row->url; ?></td> </tr> <?php } ?> </tbody> </table> 

Откройте панель сети в Chrome Dev Tools и проверьте общее время, необходимое для получения всей страницы. В моем тесте это заняло 192 мс:

varnish initial request

Теперь обновите страницу и проверьте общее время, которое требуется снова. Это заняло у меня 90 мс:

varnish second request

Давайте также проверим заголовки ответа, которые мы получаем от второго запроса:

varnish response headers

Здесь важно отметить Age и заголовки X-Varnish . При первоначальном запросе определенной страницы значение Age имеет значение 0 , и оно будет увеличиваться при последующих запросах. Вы знаете, что Varnish работает, когда вы видите, что Age увеличивается каждый раз, когда вы обновляете одну и ту же страницу. Заголовок X-Varnish имеет одно значение при первом запросе страницы. Он будет иметь два значения, когда получит что-то из кэша. Первое значение — это идентификатор запроса — уникальный идентификатор, назначаемый лаком для этого конкретного запроса страницы. Второе значение — это идентификатор запроса, из которого был заполнен кэшированный ответ, который в основном является идентификатором запроса из начального запроса страницы.

Библиотеки

В этом разделе я сделаю краткий обзор некоторых библиотек PHP, которые вы можете использовать для кэширования.

Доктрина Кеш

Doctrine — это кеширующий компонент реляционного картографа объекта Doctrine. Это позволяет использовать разные драйверы для кэширования пользовательских данных. Драйверы включают APC, Memcache, Memcached, XCache и Redis.

Вы можете установить его, выполнив следующую команду из вашего терминала:

 composer require doctrine/cache 

Вот пример того, как кэшировать пользовательские данные на сервере memcached:

 require 'vendor/autoload.php'; $memcached = new Memcached(); $port = 11211; $memcached->addServer($memcache_host, $port); $cacheDriver = new \Doctrine\Common\Cache\MemcachedCache(); $cacheDriver->setMemcached($memcached); $cacheDriver->save($cache_id, $my_data); 

Сначала мы инициализируем memcached. Затем мы устанавливаем сервер memcached, вызывая метод setMemcached и передавая ему экземпляр memcached, который мы объявили ранее. Наконец, мы кешируем данные, вызывая метод save . Эта функция требует уникального идентификатора в качестве первого аргумента и данных в качестве второго аргумента.

Вы можете найти больше информации о том, как подключиться с помощью определенного драйвера в их официальной документации .

копить

Как и Doctrine Cache, Stash — это библиотека для кэширования PHP. Это позволяет нам кэшировать результаты от вызовов базы данных, дорогостоящих вычислений и данных, которые мы можем повторно использовать во всем приложении. Он также поддерживает разные драйверы:

  • FileSystem — хранит элементы в файловой системе.
  • Sqlite — сохраняет элементы в базе данных sqlite.
  • APC — кеш на основе памяти, использующий PHP-расширение APC.
  • Memcached — использует memcached сервер для хранения предметов.
  • Redis — хранит элементы в системе хранения ключ / значение.
  • Ephemeral — кеширует элемент на весь срок действия сценария.
  • Композитный — позволяет использовать вышеуказанные драйверы в качестве одного кеша.

В этой статье я расскажу вам только об использовании Stash с Memcached, поскольку мы уже использовали его ранее.

Установка Stash

Вы можете установить Stash с помощью Composer:

 composer require tedivm/stash 

Пробовать тайник

Если вы следовали ранее в разделе Varnish и вставили данные SQL, вы можете подключиться к той же базе данных. Далее подключитесь к серверу Memcached. В отличие от Doctrine Cache, Stash предоставляет собственную оболочку для подключения к Memcached, поэтому мы будем использовать ее вместо класса, предоставляемого расширением Memcached PHP.

 $driver = new Stash\Driver\Memcache(); $driver->setOptions(array('servers' => array(MEMCACHED_HOST, MEMCACHED_PORT))); 

Теперь мы можем объявить новый пул для использования драйвера memcached. Пул представляет собой систему кеширования. Мы используем его для добавления или извлечения элементов из кэша. Каждый элемент представлен уникальным ключом, и значением может быть любой тип данных, поддерживаемый в PHP. Это включает в себя целые числа, логические значения, строки, массивы и объекты. Из этого пула мы используем метод getItem для извлечения определенного элемента.

Затем мы проверяем, существует ли элемент, который мы isMiss() в кэше, используя метод isMiss() . Если этот метод возвращает true то элемент еще не существует в кэше, и нам нужно извлечь его из исходного источника. В этом случае база данных. Мы перебираем полученные результаты и сохраняем их в массиве.

Как только мы перебрали все элементы, мы вызываем метод lock() в пуле. Это сообщает другим процессам, что текущий процесс генерирует новый набор данных. Затем мы вызываем метод set() для назначения данных, которые мы извлекли из базы данных, в пул. Как только это будет сделано, мы вызываем метод get() чтобы мы могли извлечь данные, которые мы кэшировали.

 $pool = new Stash\Pool($driver); $item = $pool->getItem('news'); if($item->isMiss()){ $results = $db->query("SELECT title, url FROM news"); while($row = $results->fetch_object()){ $data[] = array( 'title' => $row->title, 'url' => $row->url ); } $item->lock(); $item->set($data); } $news_items = $item->get(); ?> <table border="1"> <thead> <tr> <th>title</th> <th>url</th> </tr> </thead> <tbody> <?php foreach($news_items as $row){ ?> <tr> <td><?php echo $row['title']; ?></td> <td><?php echo $row['url']; ?></td> </tr> <?php } ?> </tbody> </table> 

Вывод

В этой статье мы рассмотрели еще несколько техник, программного обеспечения и библиотек, которые мы можем использовать для повышения производительности приложений и веб-сайтов, которые мы разрабатываем с использованием PHP. Какие подходы кеширования вы используете? Дайте нам знать!