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

25
VARNISH FOR AUTHENTICATED USERS Шуменко А.Е. ([email protected])

Upload: ledc-2014

Post on 12-Jul-2015

132 views

Category:

Documents


4 download

TRANSCRIPT

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

VARNISH FOR

AUTHENTICATED

USERS

Шуменко А.Е. ([email protected])

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

О чём мы будем говорить

◻ Varnish Reverse Proxy

◻ Принципы конфигурации Varnish

◻ Зачем и как разделять кэш

◻ Кэширование для пользователей

◻ Кэширование для ролей

◻ Очистка кэша

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

❑ Browser – Varnish – Web server

❑ Жизнь запроса внутри Varnish

❑ Конфигурация Varnish (*.VCL файл)

Varnish Reverse Proxy

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

Browser – Varnish – Web server

Browser

Varnish

Cache

First

request

2nd (nth )

request

❑ Первый запрос попадает к web серверу❑ Остальные запросы обслуживаются из кэша

Web

server

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

Скорость работы 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

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

Varnish

Жизнь запроса внутри Varnish

Cache

vcl_recv{}

lookup

vcl_hash{} Web

server

pass

vcl_deliver{}

vcl_fetch

{}

hit cache

miss cache

Request (HTTP)

Response

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

Конфигурация 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);

}

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

Конфигурация 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);

}

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

Конфигурация 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);

}

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

❑ Кэширование per-user

❑ Кэширование per-role

❑ User-blocks для per-role кэширования

Зачем и как разделять кэш

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

Кэширование 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"));

}

}

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

Кэширование 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']);

}

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

Кэширование 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"));

}

}

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

Кэширование per-role:блоки “паразиты”

(user blocks)

Необходимо сделать механизм получения информации специфической для каждого пользователя (user links, корзина, избранное, личные сообщения и т.д.).

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

Кэширование 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"));

}

}

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

User-blocks для per-role кэширования:Основные вопросы при проектировании

◻ Решить как получать данные (AJAX vs ESI).

◻ Как держать кэшированную версию /user_blocks актуальной («правильно» чистим кэш в varnish).

◻ Адаптировать чужие модули (на примере flag

модуля)

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

User-blocks для per-role кэширования: получаем данные AJAX

◻ Простота

◻ Один запрос независимо от количества боков

◻ Страница «мигает»

◻ Пользователь видит лишние запросы (и технические URL)

◻ Не работает с выключенным JS

За Против

Browser

Varnish

Per-role

cache

Per-user

cache

Main

request

AJAX

response

<span class=“user-blocks" data-arg="…"></span>

Web

server

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

User-blocks для per-role кэширования:

получаем данные ESI

◻ Пользователь видит готовую страницу

◻ Не зависит от включенного JS*

◻ Каждый блок создаст свой запрос в Drupal*

◻ Сложность реализации

За Против

Browser

Varnish

Per-role

cache

Per-user

cache

Main

request

ESI

<!--esi <esi:include src="/user_blocks/... " /> -->

Web

server

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

User-blocks для per-role кэширования: включаем поддержку ESI в Varnish

Чтобы Varnish обработал ESI, необходимо ему явно указать сделать это для каждой страницы которая использует ESI. Лучше помечать такие страницы в Drupal каждый раз когда вы генерируете ESI тэг.

Varnish:

sub vcl_fetch {

/* Check if we should process ESI on this page. */

if (resp.http.DOESI == "1") {

set beresp.do_esi = true;

}

}

Drupal:drupal_add_http_header(‘DOESI’, 1);

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

User-blocks для per-role кэширования:чем можно чистить кэш в varnish

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 можно вызвать из терминала.

◻ Позволяет «тегать» кэш.

Purge Ban

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

User-blocks для per-role кэширования:тегаем Varnish

кэш из Drupal

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

/* Page callback for /user_blocks. */

function mymodule_page_user_blocks() {

global $user;

drupal_add_http_header("userblocks", $user->uid);

/* Prepare user block data. */

}

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

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);

}

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

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);

}

}

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

Полезные ссылки

Описание работы 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.

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

Спасибо за внимание!