SlideShare a Scribd company logo
VARNISH FOR 
AUTHENTICATED 
USERS 
Шуменко А.Е. (ashumenko@adyax.com)
О чём мы будем говорить 
◻ Varnish Reverse Proxy 
◻ Принципы конфигурации Varnish 
◻ Зачем и как разделять кэш 
◻ Кэширование для пользователей 
◻ Кэширование для ролей 
◻ Очистка кэша
Varnish Reverse Proxy 
❑ Browser – Varnish – Web server 
❑ Жизнь запроса внутри Varnish 
❑ Конфигурация Varnish (*.VCL файл)
Browser – Varnish – Web server 
Browser 
Varnish 
Cache 
First 
request 
2nd (nth ) 
request 
❑ Первый запрос попадает к web серверу 
❑ Остальные запросы обслуживаются из кэша 
Web 
server
Скорость работы Varnish 
Условия теста: $ ab -c10 -n50 http://mysite.my/ 
Условия теста Время теста (с) Время запроса (с) 
Web server (вся страница) 62.301 1.246 
Web server (bootstrap) 23.041 0.461 
Web server (return) 0.048 0.001 
Varnish (Холодный кэш) 1.121 0.022 
Varnish (Горячий кэш) 0.029 0.0006
Жизнь запроса внутри Varnish 
Varnish 
Cache 
vcl_recv{} 
lookup 
vcl_hash{} Web 
server 
pass 
vcl_deliver{} 
vcl_fetch 
{} 
hit cache 
miss cache 
Request (HTTP) 
Response
Конфигурация Varnish 
(vcl_recv) 
Нормализировать 
данные для web- 
приложения. 
Выбрать политику 
кэширования. 
Управление 
доступом. 
sub vcl_recv { 
/* Add custom header. */ 
set req.http.X-Forwarded-For = client.ip; 
/* Do not cache POST. */ 
if (req.request == “POST”) { 
return (pass); 
} 
/* Do not cache authenticated users and Authorization 
request. */ 
if (req.http.Authorization || req.http.Cookie) { 
return (pass); 
} 
/* Mark other request as cacheable. */ 
return (lookup); 
}
Конфигурация Varnish 
(vcl_hash) 
Возвращает ID 
запроса. 
Позволяет иметь 
разный кэш одной 
и той же страницы. 
ВАЖНО: Hash 
строится только из 
переменных 
запроса. 
sub vcl_hash { 
/* Make page ID based on request. */ 
hash_data(req.url); 
if (req.http.host) { 
hash_data(req.http.host); 
} 
else { 
hash_data(server.ip); 
} 
return (hash); 
}
Конфигурация Varnish 
(vcl_fetch) 
Указать время 
кэширования 
страницы. 
sub vcl_fetch { 
/* Cache TTL can be controlled from backend. */ 
if (beresp.http.cache-control !~ “s-maxage”) { 
/* Cache JPG images for 60 seconds. */ 
if (req.url ~ “.jpg$”) { 
set beresp.ttl = 60s; 
} 
} 
/* Unset Cookies for cached pages. */ 
if (beresp.ttl > 0s) { 
unset beresp.http.Set-Cookie; 
} 
return (deliver); 
}
Зачем и как разделять кэш 
❑ Кэширование per-user 
❑ Кэширование per-role 
❑ User-blocks для per-role кэширования
Кэширование per-user: 
VCL functions 
На практике почти не 
применимо само по 
себе. 
В большинстве, 
пользователи 
посещают разные 
страницы 
Размер кэш базы 
может колоссально 
возрасти 
sub vcl_recv { 
/* Remove cookie from pages that should be same for all 
users. */ 
if (req.url ~ ".(png|gif|jpg|swf|css|js)$") { 
unset req.http.cookie; 
} 
} 
sub vcl_hash { 
/* Add User specific (session) Cookie to page ID. */ 
if (req.http.Cookie ~ "^.*?SESS([^;]*);*.*$") { 
hash_data(regsub(req.http.Cookie, "^.*?SESS([^;]*);*.*$", 
"1")); 
} 
}
Кэширование per-role: 
Drupal Hooks 
В Drupal необходимо установить Cookie уникальное для роли пользователя (комбинации 
ролей пользователя). Используем hash() и шум для усложнения подбора Cookie чужой роли. 
/** Implements hook_user_login(). */ 
function hook_user_login($edit, $user) { 
$roles = array_filter(array_keys($user->roles)); 
sort($roles); 
$bin = hash('sha256', implode('_', $roles) . 'SECRET_KEY_ABC'); 
$params = session_get_cookie_params(); 
$expire = $params['lifetime'] ? REQUEST_TIME + $params['lifetime'] : 0; 
setcookie('BIN', $bin, $expire, $params['path'], $params['domain'], FALSE, 
$params['httponly']); 
} 
/** Implements hook_user_logout(). */ 
function hook_user_logout() { 
$params = session_get_cookie_params(); 
setcookie('BIN', '', REQUEST_TIME - 3600, $params['path'], $params['domain']); 
}
Кэширование per-role: 
VCL functions 
В Varnish необходимо добавить этот Cookie к ID (hash) всех запросов. 
sub vcl_recv { 
/* Remove cookie from pages that should be same for all users. */ 
if (req.url ~ ".(png|gif|jpg|swf|css|js)$") { 
unset req.http.cookie; 
} 
} 
sub vcl_hash { 
/* Add Role specific Cookie to page ID. */ 
if (req.http.Cookie ~ "^.*?BIN=([^;]*);*.*$") { 
hash_data(regsub(req.http.Cookie, "^.*?BIN=([^;]*);*.*$", "1")); 
} 
}
Кэширование per-role:блоки “паразиты” 
(user blocks) 
Необходимо сделать механизм получения информации специфической для каждого 
пользователя (user links, корзина, избранное, личные сообщения и т.д.).
Кэширование per-role:дополненный 
vcl_hash 
Нужен путь который будет возвращать всю персональную информацию пользователя. Его 
нужно кэшировать per-user. 
sub vcl_hash { 
if (req.http.Cookie ~ "^.*?BIN=([^;]*);*.*$") { 
/* Require session Cookie. */ 
if (req.http.Cookie ~ "^.*?SESS([^;]*);*.*$") { 
/* Enable per-user cache for selected path. */ 
if (req.url ~ "^/user_blocks.*$") { 
hash_data(regsub(req.http.Cookie, "^.*?SESS([^;]*);*.*$", "1")); 
} 
} else { error 750 “Sanity error”; } 
hash_data(regsub(req.http.Cookie, "^.*?BIN=([^;]*);*.*$", "1")); 
} 
}
User-blocks для per-role кэширования:Основные 
вопросы при проектировании 
◻ Решить как получать данные (AJAX vs ESI). 
◻ Как держать кэшированную версию 
/user_blocks актуальной («правильно» чистим 
кэш в varnish). 
◻ Адаптировать чужие модули (на примере flag 
модуля)
User-blocks для per-role кэширования: получаем 
данные AJAX 
<span class=“user-blocks" data-arg="…"></span> 
За Против 
◻ Простота 
◻ Один запрос независимо от 
количества боков 
◻ Страница «мигает» 
◻ Пользователь видит лишние запросы 
(и технические URL) 
◻ Не работает с выключенным JS 
Browser 
Varnish 
Per-role 
cache 
Per-user 
cache 
Main 
request 
AJAX 
response 
Web 
server
User-blocks для per-role кэширования: 
получаем данные ESI 
<!--esi <esi:include src="/user_blocks/... " /> --> 
За Против 
◻ Пользователь видит готовую страницу 
◻ Не зависит от включенного JS* 
◻ Каждый блок создаст свой запрос в 
Drupal* 
◻ Сложность реализации 
Browser 
Varnish 
Per-role 
cache 
Per-user 
cache 
Main 
request 
ESI 
Web 
server
User-blocks для per-role кэширования: включаем 
поддержку ESI в Varnish 
Чтобы Varnish обработал ESI, необходимо ему явно указать сделать это для каждой страницы 
которая использует ESI. Лучше помечать такие страницы в Drupal каждый раз когда вы генерируете 
ESI тэг. 
Drupal: 
drupal_add_http_header(‘DOESI’, 1); 
Varnish: 
sub vcl_fetch { 
/* Check if we should process ESI on this page. */ 
if (resp.http.DOESI == "1") { 
set beresp.do_esi = true; 
} 
}
User-blocks для per-role кэширования:чем 
можно чистить кэш в varnish 
Purge Ban 
sub vcl_hit { 
if (req.request == "PURGE") { 
purge; 
error 200 "Purged."; 
} 
} 
sub vcl_miss { 
if (req.request == "PURGE") { 
purge; 
error 200 "Purged.“; 
} 
} 
sub vcl_xxxx { 
ban("req.url ~ ^/user_blocks.*$"); 
ban("obj.http.myheader == myvalue"); 
} 
◻ Для ban доступны любые 
метаданные. 
◻ ban фильтрует только уже 
кэшированные объекты, и не мешает 
новым попасть в кэш. 
◻ ban можно вызвать из терминала. 
◻ Позволяет «тегать» кэш.
User-blocks для per-role кэширования:тегаем Varnish 
кэш из Drupal 
Лучше собирать все теги в статик переменную, и выводить в заголовки ответа в delivery 
callback страницы. Но можно и иметь разные заголовки для разных тегов. 
/* Page callback for /user_blocks. */ 
function mymodule_page_user_blocks() { 
global $user; 
drupal_add_http_header("userblocks", $user->uid); 
/* Prepare user block data. */ 
… 
}
User-blocks для per-role кэширования:очищаем 
Varnish кэш из Drupal 
Используем API модуля varnish (https://drupal.org/project/varnish) для отсылки команд в 
терминал Varnish. Для этого необходим PHP с --enable-sockets. 
/** Purge user blocks for specific user. */ 
function mymodule_purge_user_blocks($uid) { 
_varnish_terminal_run(array("ban obj.http.userblocks ~ "$uid"")); 
} 
/** Implements hook_flag(). */ 
function mymodule_flag($op, $flag, $content_id, $account, $fcid) { 
/** Invalidate user blocks (user favorites block and list) */ 
mymodule_purge_user_blocks($account->uid); 
… 
}
User-blocks для per-role кэширования:очищаем 
Varnish кэш во время запроса. 
Если нету доступа к терминалу Varnish, можно очистить кэш user-blocks прямо во время 
запроса, если в качестве тега использовалась имя сессии. 
sub vcl_recv { 
/* If user make flag action we need to clean up user-blocks cache. */ 
if (req.url ~ "^/flag/.*$") { 
/* Require session Cookie. */ 
if (req.http.Cookie ~ "^.*?SESS([^;]*);*.*$") { 
/* Clean user-blocks for this session. */ 
ban("obj.http.userblocks == " + hash_data(regsub(req.http.Cookie, "^.*? 
SESS(w*);*.*$", "1"))); 
} else { error 750 “Sanity error”; } 
return(pass); 
} 
}
Полезные ссылки 
Описание работы Varnish и VCL 
◻ https://www.varnish-cache.org/docs/3.0/reference/vcl.html 
◻ https://www.varnish-software.com/static/book/VCL_Basics.html 
Полезные модули Drupal.org 
◻ https://drupal.org/project/varnish - доступ к терминалу Varnish, позволяет быстрее 
начать с ним работу. 
◻ https://drupal.org/project/esi_api - API для создания ESI тегов, встроенный фоллбек 
на AJAX.
Спасибо за внимание!

More Related Content

PDF
Хранение, обработка и отдача статики с использованием \Zend\File. Опыт социал...
PPTX
PPT
Webuibasics - Lesson 3 - Nginx, SSI (in russian)
ODP
Ice Php Framework Preview Release
PDF
2013 09 19 кеширование на клиенте и сервере
PPTX
сотни серверов, десятки компонент. автоматизация раскладки и конфигурирования...
PDF
15 - Web-технологии. Сессии и авторизация
Хранение, обработка и отдача статики с использованием \Zend\File. Опыт социал...
Webuibasics - Lesson 3 - Nginx, SSI (in russian)
Ice Php Framework Preview Release
2013 09 19 кеширование на клиенте и сервере
сотни серверов, десятки компонент. автоматизация раскладки и конфигурирования...
15 - Web-технологии. Сессии и авторизация

What's hot (20)

PDF
Олег Годовых «Страх и ненависть в Event Bus»
PDF
Страх и ненависть в Event Bus
PPT
Эффективное программирование на NodeJS
PPTX
05 db server_deployment_ru
PPT
Tapestry it is simple
PPTX
JavaScript-модули "из прошлого в будущее"
PDF
Вячеслав Олиянчук — Яндекс.Авто 2.0 на Node.js
PPT
Drupal 7 и history.js или как ajax инфицировать сайт
PPT
Загрузка, обработка, хранение и отдача статики
PPT
Drupal 7 and History.js
PDF
Building the Enterprise infrastructure with PostgreSQL as the basis for stori...
PPTX
07 virtual hosts_ru
PDF
«Изоморфные js приложения с использованием catberry.js», Денис Речкунов
PPTX
Публичный IaaS на базе ПО с открытым кодом
PDF
Making Scalable JavaScript Application
PDF
Introduction in Node.js (in russian)
KEY
Chef коротко об инфраструктуре
PDF
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)
PDF
Олег Годовых «Страх и ненависть в Event Bus»
Страх и ненависть в Event Bus
Эффективное программирование на NodeJS
05 db server_deployment_ru
Tapestry it is simple
JavaScript-модули "из прошлого в будущее"
Вячеслав Олиянчук — Яндекс.Авто 2.0 на Node.js
Drupal 7 и history.js или как ajax инфицировать сайт
Загрузка, обработка, хранение и отдача статики
Drupal 7 and History.js
Building the Enterprise infrastructure with PostgreSQL as the basis for stori...
07 virtual hosts_ru
«Изоморфные js приложения с использованием catberry.js», Денис Речкунов
Публичный IaaS на базе ПО с открытым кодом
Making Scalable JavaScript Application
Introduction in Node.js (in russian)
Chef коротко об инфраструктуре
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)
Ad

Viewers also liked (18)

PDF
Караиванов Георгий - Drupal в проектах Электронного правительства
PPTX
Александр Даниленко - Panels как философия
PPTX
Алексей Горобец - Building Drupal Distributions. Why? When? and How?
PPT
Алексей Колосов - Типичные ошибки разработчиков на Drupal (версии 5,6,7)
PDF
Тарас Круц - Tips On Getting Everything You Can Out of Drupal Form API
PPTX
Березовский Андрей - Social Authentication
PPTX
Евгений Гарбузов - E-commerce. Создание интернет-магазина на базе Drupal Comm...
PDF
Чеботарь Кирилл - Panels - пособие для начинающих
PPT
Сергей Мирошниченко - SEO-friendly data migration
PDF
Денис Головняк - Продвинутый поиск с помощью Search API
PPTX
Артем Сыльчук - Хранение полей в Drupal. От CCK к FieldableEntityStorageContr...
PPTX
Анатолий Поляков - Drupal.ajax framework from a to z
PPTX
Александр Бондаренко - CommerceBox - Почему мы решили перевести нашу сборку н...
PDF
Андрей Поданенко - Start using Vagrant now!
PPTX
Иван Фесюк - ApacheSolr+DrupalCommerce связка для высоко нагруженых проектов
PDF
Тарас Цюпер - Мультиязычность в Drupal 8
PPTX
Виктор Левандовский - Why Drupal? Как продавать Родину с напильником.
PDF
Максим Ринг - Тестирование миграции и импорта
Караиванов Георгий - Drupal в проектах Электронного правительства
Александр Даниленко - Panels как философия
Алексей Горобец - Building Drupal Distributions. Why? When? and How?
Алексей Колосов - Типичные ошибки разработчиков на Drupal (версии 5,6,7)
Тарас Круц - Tips On Getting Everything You Can Out of Drupal Form API
Березовский Андрей - Social Authentication
Евгений Гарбузов - E-commerce. Создание интернет-магазина на базе Drupal Comm...
Чеботарь Кирилл - Panels - пособие для начинающих
Сергей Мирошниченко - SEO-friendly data migration
Денис Головняк - Продвинутый поиск с помощью Search API
Артем Сыльчук - Хранение полей в Drupal. От CCK к FieldableEntityStorageContr...
Анатолий Поляков - Drupal.ajax framework from a to z
Александр Бондаренко - CommerceBox - Почему мы решили перевести нашу сборку н...
Андрей Поданенко - Start using Vagrant now!
Иван Фесюк - ApacheSolr+DrupalCommerce связка для высоко нагруженых проектов
Тарас Цюпер - Мультиязычность в Drupal 8
Виктор Левандовский - Why Drupal? Как продавать Родину с напильником.
Максим Ринг - Тестирование миграции и импорта
Ad

Similar to Александр Шуменко - Varnish for authenticated users (20)

PDF
Повышаем производительность Drupal-сайта
PDF
The Old New ASP.NET
PDF
Phalcon - самый быстрый PHP Framework
PPTX
Взломать сайт на ASP.NET
PPT
Стажировка-2014, занятие 8. Обзор Sails framework (Node.js)
ODP
Nginx Igor Sysoev
PPTX
Web deployment
PPT
PHP Tricks
PDF
.NET Fest 2018. Сергей Калинец. Azure веб разработка здорового человека
PPTX
Node.js введение в технологию, КПИ #ITmeetingKPI
PPTX
Silverlight 4, есть ли жизнь на десктопе
PDF
Истинный DevOps. Секрет 42.
PPTX
Алексей Морозов (Россия), Rambler.ru. ASP.NET в помощь хакеру и не только....
PPTX
SharePoint Virtualization "Виртуальный SharePoint 2010"
PDF
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
PDF
Frontend весна 2014 лекция 1
PPTX
Что нового в ASP.NET 4
PPTX
PHP 5.4: Что нового?
PDF
Антон Каляев — Быстрое развертывание среды с Vagrant
PPT
Арсений Заречнев и Федор Шумов - Одностраничные приложения
Повышаем производительность Drupal-сайта
The Old New ASP.NET
Phalcon - самый быстрый PHP Framework
Взломать сайт на ASP.NET
Стажировка-2014, занятие 8. Обзор Sails framework (Node.js)
Nginx Igor Sysoev
Web deployment
PHP Tricks
.NET Fest 2018. Сергей Калинец. Azure веб разработка здорового человека
Node.js введение в технологию, КПИ #ITmeetingKPI
Silverlight 4, есть ли жизнь на десктопе
Истинный DevOps. Секрет 42.
Алексей Морозов (Россия), Rambler.ru. ASP.NET в помощь хакеру и не только....
SharePoint Virtualization "Виртуальный SharePoint 2010"
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Frontend весна 2014 лекция 1
Что нового в ASP.NET 4
PHP 5.4: Что нового?
Антон Каляев — Быстрое развертывание среды с Vagrant
Арсений Заречнев и Федор Шумов - Одностраничные приложения

More from LEDC 2016 (20)

PPTX
A. Postnikov & P. Mahrinsky — Drupal Community — це ми
PDF
Слава Мережко — Практикум: "Як ростити розробників"
PDF
Генадій Колтун — Комунізм наступає: що будемо робити, коли машини навчаться п...
PDF
Олексій Калініченко — Configuration Management in Drupal8
PPTX
Олександр Лінивий — Multisite platform with continuous delivery process for m...
PPTX
Андрій Юн — Воркшоп "Docker use cases for developers"
PDF
Андрій Поданенко — Воркшоп "Розвертання CIBox"
PDF
Юрій Герасімов — Editorial experience in Drupal8
PPTX
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
PPTX
Тарас Кирилюк — Docker basics. How-to for Drupal developers
PDF
Тарас Круц — Open Social: brand new Drupal 8 distro for building social netwo...
PDF
Ігор Карпиленко — PHPStorm for drupal developer
PDF
Олександр Щедров — Build your application in seconds and optimize workflow as...
PPTX
Анатолій Поляков — Subdomains everywhere
PPTX
Артем Доценко — Deploy Plus. Better UI and more control for deploy module
PPTX
Сергій Бондаренко — Тестування Drupal сайтiв з допогою TqExtension
PPTX
Вадим Абрамчук — Big Drupal: Issues We Met
PDF
Юрій Герасимов — Delayed operations with queues
PPTX
Віталій Бобров — Web components, Polymer and Drupal
PPTX
Олександр Щедров та Альбіна Тюпа — Magic button. Can production releases be s...
A. Postnikov & P. Mahrinsky — Drupal Community — це ми
Слава Мережко — Практикум: "Як ростити розробників"
Генадій Колтун — Комунізм наступає: що будемо робити, коли машини навчаться п...
Олексій Калініченко — Configuration Management in Drupal8
Олександр Лінивий — Multisite platform with continuous delivery process for m...
Андрій Юн — Воркшоп "Docker use cases for developers"
Андрій Поданенко — Воркшоп "Розвертання CIBox"
Юрій Герасімов — Editorial experience in Drupal8
Валентин Мацвейко та Владислав Мойсеєнко — D8: Migrate Yourself: code->module...
Тарас Кирилюк — Docker basics. How-to for Drupal developers
Тарас Круц — Open Social: brand new Drupal 8 distro for building social netwo...
Ігор Карпиленко — PHPStorm for drupal developer
Олександр Щедров — Build your application in seconds and optimize workflow as...
Анатолій Поляков — Subdomains everywhere
Артем Доценко — Deploy Plus. Better UI and more control for deploy module
Сергій Бондаренко — Тестування Drupal сайтiв з допогою TqExtension
Вадим Абрамчук — Big Drupal: Issues We Met
Юрій Герасимов — Delayed operations with queues
Віталій Бобров — Web components, Polymer and Drupal
Олександр Щедров та Альбіна Тюпа — Magic button. Can production releases be s...

Александр Шуменко - Varnish for authenticated users

  • 1. VARNISH FOR AUTHENTICATED USERS Шуменко А.Е. (ashumenko@adyax.com)
  • 2. О чём мы будем говорить ◻ Varnish Reverse Proxy ◻ Принципы конфигурации Varnish ◻ Зачем и как разделять кэш ◻ Кэширование для пользователей ◻ Кэширование для ролей ◻ Очистка кэша
  • 3. Varnish Reverse Proxy ❑ Browser – Varnish – Web server ❑ Жизнь запроса внутри Varnish ❑ Конфигурация Varnish (*.VCL файл)
  • 4. Browser – Varnish – Web server Browser Varnish Cache First request 2nd (nth ) request ❑ Первый запрос попадает к web серверу ❑ Остальные запросы обслуживаются из кэша Web server
  • 5. Скорость работы Varnish Условия теста: $ ab -c10 -n50 http://mysite.my/ Условия теста Время теста (с) Время запроса (с) Web server (вся страница) 62.301 1.246 Web server (bootstrap) 23.041 0.461 Web server (return) 0.048 0.001 Varnish (Холодный кэш) 1.121 0.022 Varnish (Горячий кэш) 0.029 0.0006
  • 6. Жизнь запроса внутри Varnish Varnish Cache vcl_recv{} lookup vcl_hash{} Web server pass vcl_deliver{} vcl_fetch {} hit cache miss cache Request (HTTP) Response
  • 7. Конфигурация Varnish (vcl_recv) Нормализировать данные для web- приложения. Выбрать политику кэширования. Управление доступом. sub vcl_recv { /* Add custom header. */ set req.http.X-Forwarded-For = client.ip; /* Do not cache POST. */ if (req.request == “POST”) { return (pass); } /* Do not cache authenticated users and Authorization request. */ if (req.http.Authorization || req.http.Cookie) { return (pass); } /* Mark other request as cacheable. */ return (lookup); }
  • 8. Конфигурация Varnish (vcl_hash) Возвращает ID запроса. Позволяет иметь разный кэш одной и той же страницы. ВАЖНО: Hash строится только из переменных запроса. sub vcl_hash { /* Make page ID based on request. */ hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } return (hash); }
  • 9. Конфигурация Varnish (vcl_fetch) Указать время кэширования страницы. sub vcl_fetch { /* Cache TTL can be controlled from backend. */ if (beresp.http.cache-control !~ “s-maxage”) { /* Cache JPG images for 60 seconds. */ if (req.url ~ “.jpg$”) { set beresp.ttl = 60s; } } /* Unset Cookies for cached pages. */ if (beresp.ttl > 0s) { unset beresp.http.Set-Cookie; } return (deliver); }
  • 10. Зачем и как разделять кэш ❑ Кэширование per-user ❑ Кэширование per-role ❑ User-blocks для per-role кэширования
  • 11. Кэширование per-user: VCL functions На практике почти не применимо само по себе. В большинстве, пользователи посещают разные страницы Размер кэш базы может колоссально возрасти sub vcl_recv { /* Remove cookie from pages that should be same for all users. */ if (req.url ~ ".(png|gif|jpg|swf|css|js)$") { unset req.http.cookie; } } sub vcl_hash { /* Add User specific (session) Cookie to page ID. */ if (req.http.Cookie ~ "^.*?SESS([^;]*);*.*$") { hash_data(regsub(req.http.Cookie, "^.*?SESS([^;]*);*.*$", "1")); } }
  • 12. Кэширование per-role: Drupal Hooks В Drupal необходимо установить Cookie уникальное для роли пользователя (комбинации ролей пользователя). Используем hash() и шум для усложнения подбора Cookie чужой роли. /** Implements hook_user_login(). */ function hook_user_login($edit, $user) { $roles = array_filter(array_keys($user->roles)); sort($roles); $bin = hash('sha256', implode('_', $roles) . 'SECRET_KEY_ABC'); $params = session_get_cookie_params(); $expire = $params['lifetime'] ? REQUEST_TIME + $params['lifetime'] : 0; setcookie('BIN', $bin, $expire, $params['path'], $params['domain'], FALSE, $params['httponly']); } /** Implements hook_user_logout(). */ function hook_user_logout() { $params = session_get_cookie_params(); setcookie('BIN', '', REQUEST_TIME - 3600, $params['path'], $params['domain']); }
  • 13. Кэширование per-role: VCL functions В Varnish необходимо добавить этот Cookie к ID (hash) всех запросов. sub vcl_recv { /* Remove cookie from pages that should be same for all users. */ if (req.url ~ ".(png|gif|jpg|swf|css|js)$") { unset req.http.cookie; } } sub vcl_hash { /* Add Role specific Cookie to page ID. */ if (req.http.Cookie ~ "^.*?BIN=([^;]*);*.*$") { hash_data(regsub(req.http.Cookie, "^.*?BIN=([^;]*);*.*$", "1")); } }
  • 14. Кэширование per-role:блоки “паразиты” (user blocks) Необходимо сделать механизм получения информации специфической для каждого пользователя (user links, корзина, избранное, личные сообщения и т.д.).
  • 15. Кэширование per-role:дополненный vcl_hash Нужен путь который будет возвращать всю персональную информацию пользователя. Его нужно кэшировать per-user. sub vcl_hash { if (req.http.Cookie ~ "^.*?BIN=([^;]*);*.*$") { /* Require session Cookie. */ if (req.http.Cookie ~ "^.*?SESS([^;]*);*.*$") { /* Enable per-user cache for selected path. */ if (req.url ~ "^/user_blocks.*$") { hash_data(regsub(req.http.Cookie, "^.*?SESS([^;]*);*.*$", "1")); } } else { error 750 “Sanity error”; } hash_data(regsub(req.http.Cookie, "^.*?BIN=([^;]*);*.*$", "1")); } }
  • 16. User-blocks для per-role кэширования:Основные вопросы при проектировании ◻ Решить как получать данные (AJAX vs ESI). ◻ Как держать кэшированную версию /user_blocks актуальной («правильно» чистим кэш в varnish). ◻ Адаптировать чужие модули (на примере flag модуля)
  • 17. User-blocks для per-role кэширования: получаем данные AJAX <span class=“user-blocks" data-arg="…"></span> За Против ◻ Простота ◻ Один запрос независимо от количества боков ◻ Страница «мигает» ◻ Пользователь видит лишние запросы (и технические URL) ◻ Не работает с выключенным JS Browser Varnish Per-role cache Per-user cache Main request AJAX response Web server
  • 18. User-blocks для per-role кэширования: получаем данные ESI <!--esi <esi:include src="/user_blocks/... " /> --> За Против ◻ Пользователь видит готовую страницу ◻ Не зависит от включенного JS* ◻ Каждый блок создаст свой запрос в Drupal* ◻ Сложность реализации Browser Varnish Per-role cache Per-user cache Main request ESI Web server
  • 19. User-blocks для per-role кэширования: включаем поддержку ESI в Varnish Чтобы Varnish обработал ESI, необходимо ему явно указать сделать это для каждой страницы которая использует ESI. Лучше помечать такие страницы в Drupal каждый раз когда вы генерируете ESI тэг. Drupal: drupal_add_http_header(‘DOESI’, 1); Varnish: sub vcl_fetch { /* Check if we should process ESI on this page. */ if (resp.http.DOESI == "1") { set beresp.do_esi = true; } }
  • 20. User-blocks для per-role кэширования:чем можно чистить кэш в varnish Purge Ban sub vcl_hit { if (req.request == "PURGE") { purge; error 200 "Purged."; } } sub vcl_miss { if (req.request == "PURGE") { purge; error 200 "Purged.“; } } sub vcl_xxxx { ban("req.url ~ ^/user_blocks.*$"); ban("obj.http.myheader == myvalue"); } ◻ Для ban доступны любые метаданные. ◻ ban фильтрует только уже кэшированные объекты, и не мешает новым попасть в кэш. ◻ ban можно вызвать из терминала. ◻ Позволяет «тегать» кэш.
  • 21. User-blocks для per-role кэширования:тегаем Varnish кэш из Drupal Лучше собирать все теги в статик переменную, и выводить в заголовки ответа в delivery callback страницы. Но можно и иметь разные заголовки для разных тегов. /* Page callback for /user_blocks. */ function mymodule_page_user_blocks() { global $user; drupal_add_http_header("userblocks", $user->uid); /* Prepare user block data. */ … }
  • 22. User-blocks для per-role кэширования:очищаем Varnish кэш из Drupal Используем API модуля varnish (https://drupal.org/project/varnish) для отсылки команд в терминал Varnish. Для этого необходим PHP с --enable-sockets. /** Purge user blocks for specific user. */ function mymodule_purge_user_blocks($uid) { _varnish_terminal_run(array("ban obj.http.userblocks ~ "$uid"")); } /** Implements hook_flag(). */ function mymodule_flag($op, $flag, $content_id, $account, $fcid) { /** Invalidate user blocks (user favorites block and list) */ mymodule_purge_user_blocks($account->uid); … }
  • 23. User-blocks для per-role кэширования:очищаем Varnish кэш во время запроса. Если нету доступа к терминалу Varnish, можно очистить кэш user-blocks прямо во время запроса, если в качестве тега использовалась имя сессии. sub vcl_recv { /* If user make flag action we need to clean up user-blocks cache. */ if (req.url ~ "^/flag/.*$") { /* Require session Cookie. */ if (req.http.Cookie ~ "^.*?SESS([^;]*);*.*$") { /* Clean user-blocks for this session. */ ban("obj.http.userblocks == " + hash_data(regsub(req.http.Cookie, "^.*? SESS(w*);*.*$", "1"))); } else { error 750 “Sanity error”; } return(pass); } }
  • 24. Полезные ссылки Описание работы Varnish и VCL ◻ https://www.varnish-cache.org/docs/3.0/reference/vcl.html ◻ https://www.varnish-software.com/static/book/VCL_Basics.html Полезные модули Drupal.org ◻ https://drupal.org/project/varnish - доступ к терминалу Varnish, позволяет быстрее начать с ним работу. ◻ https://drupal.org/project/esi_api - API для создания ESI тегов, встроенный фоллбек на AJAX.

Editor's Notes

  • #12: Пример сайта розетка, просматриваю много продуктов по 1 разу Сделать акцент на том что не применимо само по себе как дефолтное правило для разделения кеша, но необходимо для кешировани по ролям.
  • #13: Роли могут возвратиться в произвольном порядке поэтому необходимо их сортировать. Используем мд5 чтобы усложнить подбор куки для другой роли. Процедура формирования куки такая же как в сессион инк.
  • #14: В таком виде не применимо так как зареганые пользовати должны видеть разные страницы
  • #16: Ошибки обрабатываются vcl_error но мы ее не рассматриваем. Если мы собираемся учитывать куку роли, нам необходимо чтобы была установлена кука сесии Также путь к юзер блокам мы кэшируем пер юзер. /user_blocks/%uid не подходит так как юид будет для всех одинаковый.
  • #19: Стоит сказать про СЕО но для авторизированых польователей СЕО не есть приоритет.
  • #21: Правильно выбрать ТТЛ пол дела, очистку некоторых объектов предсказать нельзя, и нам обязательно иметь их актуальными.
  • #23: PHP с --enable-sockets по дефолту, но некоторые провайдеры его могут отключить.
  • #24: Потенциальное место для инжекшена ибо вы исполняем юзер инпут важно правильно сделать регулярку.