Extra Block Types (EBT) - New Layout Builder experience❗

Extra Block Types (EBT) - styled, customizable block types: Slideshows, Tabs, Cards, Accordions and many others. Built-in settings for background, DOM Box, javascript plugins. Experience the future of layout building today.

Demo EBT modules Download EBT modules

❗Extra Paragraph Types (EPT) - New Paragraphs experience

Extra Paragraph Types (EPT) - analogical paragraph based set of modules.

Demo EPT modules Download EPT modules

Scroll

Контексты кэша

30/04/2020, by maria
Кэширование контекстов = (запрос) контекстных зависимостей
Контексты кэша аналогичны HTTP-заголовку Vary.

Зачем?

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

Примеры:

  • Вывод некоторых данных зависит от активной темы и разные результаты выводятся для разных тем. Тогда вы будете использовать кэш в зависимости от контекста кэша темы.
  • При создании массива рендеринга, который показывает персонализированное сообщение, рендеринг массива зависит от пользователя. Тогда кэш будет зависить от контекста кэша пользователя.
  • Обычно: когда некоторая дорогостоящая для вычисления информация зависит от окружения сервера, то для этого также используется контекст кэша.

Каким образом?

Контекст кэша - это строка, которая ссылается на одну из доступных служб контекста кэша (см. ниже).

Контексты кэша передаются в наборах (порядок не имеет значения) строк, поэтому они печатаются в string[]. Это наборы, потому что один элемент кэша может зависеть (варьироваться) от многих контекстов кэша.

Обычно контексты кэша получают из объекта контекста запроса (то есть из запроса). Большая часть среды для веб-приложения получена из контекста запроса. В конце концов, HTTP-ответы генерируются в значительной степени в зависимости от свойств HTTP-запросов, которые их инициировали.

Но это не означает, что контексты кэша должны исходить из запроса - они также могут зависеть от развернутого кода, например, контекста deployment_id

Во-вторых, контексты кэша описаны в виде иерархии. Самый простой пример: когда что-то отличается для каждого пользователя, то нам уже не нужно использовать просто права доступа, потому что различия для каждого пользователя. Для набора прав доступа кэширование используется для каждого из прав доступа. Если одна часть страницы отличается для каждого пользователя, а другая для прав доступа, то Drupal должен быть достаточно умным, чтобы использовать различия только для каждого пользователя. Именно здесь Drupal может использовать информацию иерархии, чтобы не создавать ненужных изменений кэша.

Синтаксис

  • точки разделяют родительские элементы от дочерних
  • Имя кэша во множественном числе указывает, что может использоваться параметр: добавьте двоеточие, затем укажите желаемый параметр (если параметр не указан, будут собраны все возможные параметры, например, все аргументы запроса)

Контексты кэша ядра Drupal 8

Ядро Drupal 8 поставляется со следующей иерархией контекстов кэша:

cookies
  :name
headers
  :name
ip
languages
  :type
protocol_version // Available in 8.9.x or higher.
request_format
route
  .book_navigation
  .menu_active_trails
    :menu_name
  .name
session
  .exists
theme
timezone
url
  .path
    .is_front // Available in 8.3.x or higher.
    .parent
  .query_args
    :key
    .pagers
      :pager_id
  .site
user
  .is_super_user
  .node_grants
    :operation
  .permissions
  .roles
    :role

Примечание. Чтобы использовать контекст кэширования url.path.is_front в предыдущих ветках/релизах, см. запись об изменении.

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

  • нет двусмысленности: понятно, на чем основан родительский контекст кэша, где бы он ни использовался
  • Сравнение (и сворачивание) контекстов кэша становится проще: если присутствуют и a.b.c, и a.b, очевидно, что a.b включает в себя a.b.c, и, следовательно, понятно, почему a.b.c можно опустить, почему его можно «свернуть» в родительский объект
  • не нужно заботиться о том, чтобы каждый уровень дерева был уникальным во всем дереве

Итак, примеры контекстов кэша из этой иерархии:

  • theme (зависит от установленной темы)
  • user.roles (зависит от комбинации ролей)
  • user.roles:anonymous (зависит от того, имеет ли текущий пользователь роль «анонимный» или нет, то есть «является анонимным пользователем»)
  • languages (различаются для всех типов языков: интерфейс, контент…)
  • languages:language_interface (зависит от языка интерфейса - LanguageInterface::TYPE_INTERFACE)
  • languages:language_content (зависит от языка контента - LanguageInterface::TYPE_CONTENT)
  • URL (зависит от всего URL)
  • url.query_args (зависит от всей строки запроса)
  • url.query_args:foo (зависит от аргумента запроса? foo)
  • protocol_version (зависит от HTTP 1 против 2)

Оптимизация/сворачивание/объединение/упрощение контекстов кэша

Drupal автоматически использует информацию об иерархии, чтобы максимально упростить контексты кэша. Например, когда одна часть страницы изменяется для пользователя (контекст кэша user), а другая часть страницы изменяется для разрешения (контекст кэша user.permissions), тогда нет смысла изменять конечный результат в разрешениях, так как изменения будут для каждого пользователя отдельно.
Другими словами: optimize([user, user.permissions]) = [user].

Даже если пользователь действительно подразумевает user.permissions, потому что он более конкретен, если мы оптимизируем user.permissions, любые изменения в разрешениях больше не приводят к тому, что контекст кэша user.permissions будет загружаться для каждой страницы. Это означает, что если разрешения меняются, мы все равно продолжаем использовать ту же кешированную версию, даже если она должна меняться при каждом изменении разрешений.

Вот почему контексты кэша, которые зависят от конфигурации, которая может меняться со временем, могут связывать метаданные кэшируемости: теги кэша и максимальный возраст (max-age). Когда такой контекст кэша оптимизируется, его теги кэша ассоциируются с элементом кэша. Следовательно, всякий раз, когда назначенные разрешения изменяются, элемент кэша также становится недействительным.

(Помните, что «кэширование» - это, по сути, «избежание ненужных вычислений». Поэтому оптимизацию контекста можно рассматривать как кэширование результата метода getContext() службы контекста. В данном случае это неявный кеш (значение отбрасывается вместо того, чтобы сохранять), но эффект тот же: при попадании в кеш метод getContext() не вызывается, следовательно: вычислений избегают. А когда мы что-то кешируем, мы связываем кешируемость этой вещи, поэтому в случае кешируем контексты, мы связываем теги и max-age.)

Аналогичным, но более сложным примером являются node grants. Node grants применяются к конкретному пользователю, поэтому контекст кэша разрешений ноды имеет вид user.node_grants За исключением того, что разрешения ноды могут быть чрезвычайно динамичными (они могут, например, зависеть от времени и изменяться каждые несколько минут). Это зависит от реализаций хуков node grant, представленных на сайте. Следовательно, лучше использовать контекст кеша node grants, с max-age = 0, означающий, что он не может быть кеширован (то есть оптимизирован). Следовательно, optimize([user, user.node_grants]) = [user, user.node_grants].

Определенные сайты могут переопределить реализацию контекста кэширования разрешений для узла по умолчанию и вместо этого указать max-age = 3600, указывая, что все их перехватчики разрешений узла позволяют кэшировать результаты доступа не более часа. На таких сайтах оптимизируйте optimize([user, user.node_grants]) = [user].

Как распознать, определить и создать?

Контексты кэша - это сервисы с тегами cache.context. Таким образом, любой модуль может добавить контексты кеша. Они реализуют \Drupal\Core\Cache\Context\CacheContextInterface или \Drupal\Core\Cache\Context\CalculatedCacheContextInterface (для контекстов кэша, которые принимают параметры, т.е. контексты кэша, которые принимают суффикс :parameter).

Следовательно, все, что вам нужно сделать, чтобы найти все контексты кэша, которые у вас есть для использования, - это перейти к CacheContextInterface и CalculatedCacheContextInterface и использовать вашу IDE, чтобы найти все его реализации. (В PHPStorm: Иерархия типов → Иерархия подтипов в NetBeans: щелкните правой кнопкой мыши имя интерфейса → Найти использование → Найти все подтипы.)

В качестве альтернативы вы можете использовать консоль Drupal (drupal debug:cache:context) для отображения всех текущих контекстов кэша для вашего сайта или приложения:

$ drupal debug:cache:context
 Context ID               Label                             Class path                                               
 cookies                  HTTP-Cookies                      Drupal\Core\Cache\Context\CookiesCacheContext            
 headers                  HTTP-Header                       Drupal\Core\Cache\Context\HeadersCacheContext            
 ip                       IP-Adresse                        Drupal\Core\Cache\Context\IpCacheContext                 
 languages                Language                          Drupal\Core\Cache\Context\LanguagesCacheContext          
 request_format           Anfrageformat                     Drupal\Core\Cache\Context\RequestFormatCacheContext      
 route                    Route                             Drupal\Core\Cache\Context\RouteCacheContext              
 route.book_navigation    Buchnavigation                    Drupal\book\Cache\BookNavigationCacheContext             
 route.menu_active_trails Aktiver Menüpfad                  Drupal\Core\Cache\Context\MenuActiveTrailsCacheContext

В каждом найденном вами классе вы увидите такой комментарий \Drupal\Core\Cache\Context\UserCacheContext:

Cache context ID: 'user'.

Это означает, что 'user' - это фактический контекст кэша, который вы можете указать в коде. (В качестве альтернативы найдите, где этот класс используется в файле *.services.yml, и посмотрите идентификатор службы. Подробнее об этом ниже.)

Совет: Вы можете получить актуальный полный список всех контекстов кеша в ядре Drupal, только взглянув на сервисы, помеченные cache_context!

Идентификатор услуги стандартизирован. Он всегда начинается с cache_context., За которым следуют родители контекста кеша, и, наконец, имя контекста кеша. Так, например: cache_context (обязательный префикс) + route (parent) + book_navigation (имя этого контекста кэша):

cache_context.route.book_navigation:
    class: Drupal\book\Cache\BookNavigationCacheContext
    arguments: ['@request_stack']
    tags:
      - { name: cache.context }

Это определяет контекст кеша route.book_navigation.

Отладка

Все вышеперечисленное является полезной информацией при отладке чего-либо, что кэшируется. Но есть еще одна вещь: скажем, что-то кешируется с ключами кэша ['foo', 'bar'] и контекстами кэша ['languages:language_interface', 'user.permissions', 'route']. Затем соответствующий элемент кэша будет кэшироваться в конкретном контейнере кэша с CID (идентификатором кэша):

foo:bar:[languages:language_interface]=en:[user.permissions]=A_QUITE_LONG_HASH:[route]=myroute.ROUTE_PARAMS_HASH

Другими словами:

  • ключи кеша перечислены первыми, в указанном порядке
  • контексты кэша перечисляются вторыми в алфавитном порядке и приводят к частям CID в форме [<cache context name>]=<cache context value>
  • все эти части CID объединяются с помощью двоеточий

Это должно облегчить анализ и отладку кешей!

Заголовки (отладка)

И наконец: легко увидеть, от каких контекстов кэша зависит определенный ответ (и, следовательно, он варьируется): достаточно взглянуть только на заголовок X-Drupal-Cache-Contexts!

Примечание. Если вы не видите эти заголовки, вам нужно настроить экземпляр Drupal для разработки.

Динамический кэш страницы

Всестороннее использование контекстов кэша в Drupal 8 позволяет Drupal 8 поставляться с включенным по умолчанию динамическим кэшем страниц. (Ранее известный как «Smart Cache»)

Внутренний кэш страницы

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

Смотрите также

Source URL:

Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.