CloudFlare + nginx, або економимо при допомоги «кавоварки»


Добрий день, шановний %username%, жадібний читач і борець за справедливість в інтернеті!

Всі ми пам'ятаємо (гугл точно пам'ятає!), була така стаття CloudFlare + nginx = кешируем все на безкоштовному плані. У якій розглядалися основні принципи економії на тарифах і серверах, шляхом всеїдного кешування на стороні CloudFlare файлів до 512Мб.

У даному матеріалі ми пограємо з кодами відповідей нашого сервера, щоб зекономити ще більше золота щоб побудувати зіккурат і не переходити на «enterprise plan» які нам «offer» схожий результат у своїх «offers».

На безкоштовному тариф TTL становить 2 години. Це те, що у них написано в безкоштовному тарифному плані. Якщо ж копнути глубже, то отримуємо:

  • 200 301 120m;
  • 302 303 20m;
  • 403 1m;
  • 404 5m;
  • any 0s;
Більш розгорнуто: редиректи кешируются за 20 хвилин, помилки авторизації на хвилину і класичні 404 по 5 хвилин. Інші коди не кешируются.

Це означає, що якщо у вас класний динамічний сайт який, наприклад, надає API для яких-небудь операцій і т. д. і т. п. і це у вас загорнуте через CF, так як генерує файли і картинки та багато трафіку, а динаміці боляче… то якщо хтось розуміє як у вас генеруються відповіді (голий лічильник або в base64 або свій base або хеши, але останні підібрати важче), то він (людина з темної сторони кімнати без освітлення) може обдурити інших користувачів помилковим відповіддю, а саме — 404.

Наприклад:

  • Простий сервіс, який смикає EXIF з фоток, які були залиті. Приклад посилання
    http://example.com/api/image/exif/1.txt
    — що означає видати EXIF як TXT з фотки з id=1.
Припустимо, що у вас там 1336 фоток. Се значить, що 1, 2..1336ая выдатут 200й відповідь, який буде закеширован на стороні cloudflare.

Ось наша емуляція (nginx):

location ~* "^/api/image/exif/(.*?)\.txt$" {
default_type text/plain;
set $testimageid $1;
##backend
if ($testimageid ~ 1337){
return 404 "Image $testimageid not found";
}
##backend
return 200 "EXIF for $testimageid image";
}



І так далі…



Поки не дійдемо до фото з айді 1337, якого на сервері немає. Що зробить наша динаміка? Логічно, що вона видасть якийсь текст про помилку і код 404.


Який слідом буде закеширован. І всі наступні запити до цього URL видадуть відповідь з кеша CF на наступні 5 хвилин.

Критично це? І так, і ні. Залежить від того, скільки юзерів ви зробите нещасними і скільки съекономленных на CDN (завдяки мені) мільйонів ви втратите.

Що ж робити? Дивимося оффициальный матеріал і розуміємо, що треба змінювати код… код відповіді сервера у разі 404.

Але не все так просто. Нельзя_просто_так_взять_и_сменить_код_ответа.јрд, так як кожний код несе якусь смислове навантаження, яка буде інтерпретована або на неї просто заб'ють!

Ось для цього і був придуманий код, який ніякого смислового навантаження не несе, це код 418, який описаний в rfc2324.

Міняємо код нашої емуляції (і очищаємо кеш для цього посилання в панелі CF):

location ~* "^/api/image/exif/(.*?)\.txt$" {
default_type text/plain;
set $testimageid $1;
##backend
if ($testimageid ~ 1337){
return 418 "Image $testimageid not found";
}
##backend
return 200 "EXIF for $testimageid image";
}

І отримуємо таку картину:



Це знаменує факт, що до тих пір, поки картинки немає, CF не кешує відповідь від нашого сервера, передаючи клієнтам кожен раз свіжий відповідь з помилкою 418 [від нашого сервера]. Слідом, як картинка з'являється на сервері, і наша динаміка віддає відповідь 200, CF кешує цей відповідь на 2 години.

Код 418 відноситься до 4хх групі кодів. І навіть, якщо у користувача немає визначення цього коду в браузері (або в самописному софті), то там є як мінімум (повинна бути!) перевірка на 4хх як на скріншотах цієї статті (firefox, червоненький квадратик).

Ось так просто можна повідомити про помилку (4хх) і попросити cloudflare не кешувати даний відповідь при політиці, коли ми всі кешируем. Це вберігає від помилкових 404 відповідей від сервера, коли хтось запитував майбутній матеріал до моменту публікації.

Та прибуде з вами сила!

З. И.
set $testimageid $1;
використовується тому, що nginx не може порівнювати $1 if вираженні (але може оперувати $1 в конфіги або в контенті), для цього треба вводити змінну. Щербаті котли картинки вирівнюються між собою і стиснуті в png-8, перфекціоністи на діалап можуть посміхнутися!
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.