WooCommerce, LiteSpeed и QUIC.cloud CDN

Тази статия ще бъде доста по-дълга от обичайното, понеже имам да споделя много интересни неща, които научих наскоро, докато мигрирах WooCommerce сайта на мой клиент от „най-големия“ хостинг оператор в България към услугата на друг, далеч по-перспективен хостер. Тъй като целта на настоящия коментар е да споделя наблюденията си по отношение на производителността и уникалните предимства на новата услуга, а не да правя реклама някому, умишлено няма да споменавам имена. Но ако много държите да знаете, питайте 🙂

Какъв проблем търсим да решим?

Основният проблем на хостинг услугата, която моят клиент ползваше до момента, беше ниската скорост на зареждане въпреки правилното конфигуриране на кеширането и използването на всички допълнителни възможни инструменти на разположение в стека на хостинг оператора.

Проблемът е донякъде следствие от остарялата технология, която се използва масово от хостинг компаниите: Apache сървър, PHP FPM процесор, кеширащ модул като memcached или redis и дотам (някои по-„авангардни“ оператори предлагат и Ngnix вместо Apache…). Ако клиентът иска CDN, оптимизация на изображения, CSS и JS ресурси, той трябва да търси решение другаде и да го интегрира върху този стек.

По-съвременното решение се явява в лицето на LiteSpeed Web Server — технологичен стек от много по-ново поколение, който интегрира в себе си функциите на web сървъра, PHP процесор и кеширащи модули. Архитектурата на това решение е замислена по такъв начин, че да позволява взаимодействие върху стека и приложението, което се изпълнява върху него. Тоест, приложението (в най-общия случай — web сайтът) може да си комуникира със сървъра посредством API интерфейс и да управлява процесите за генериране на статично съдържание, минифициране на HTML, CSS и JS съдържание, динамично кеширане и др.

А благодарение на тясната интеграция с Quic.Cloud, за която ще стане дума най-накрая, този технологичен стек и приложение могат да бъдат разширени с CDN, компресия и конверсия на изображения в next-gen формат и други функции, благодарение на което цялостният процес на зареждане на web страниците се изпълнява по-бързо и сървърът може да изпълнява много повече заявки с ниско TTFB, а браузерът на клиента да „изплюва“ готовите страници по-скоростно.

Вариантите на LiteSpeed

LiteSpeed има две версии: OpenLiteSpeed (напълно безплатна)и LiteSpeed Webserver, Enterprise edition (накратко LSWE). Моят опит е именно с LSWE, но от потребителска гледна точка двата софтуера поддържат еднакъв набор функции.

LSWE е предвидена да се използва от хостинг оператори и включва техническа поддръжка, както и съвместимост с две важни функции на Apache: интерпретация на формата на vhost файловете и mod_rewrite директивите. От гледна точка на този тип потребители софтуерът се явява директен заместител (drop-in replacement) на Apache: достатъчно е да спрете Apache, да инсталирате LSWE, да го настроите да слуша на портове 80 и 443, и да го насочите откъде да чете конфигурацията за виртуалните хостове.

Освен самия web сървър, разработчиците на LiteSpeed предлагат набор от безплатни кеширащи модули (LSCache) за най-популярните CMS системи:

  • WordPress (вкл. WooCommerce)
  • Joomla
  • Drupal
  • Magento
  • PrestaShop
  • OpenCart
  • Laravel

Важно е да разберете фундаменталната разлика между LSWE/OpenLiteSpeed и всичко останало, с което сте работили досега: вместо да разчитат на вас (разработчика, архитекта) да сглобите стека, върху който ще се изпълнява приложението, LiteSpeed ви предоставят готов стек: в него е интегриран HTTP сървър, HTTPS/TLS модул за поддръжка на съвременни криптографски примитиви и протоколи за комуникация в интернет среда, специално компилиран собствен PHP процесор (вместо отделен PHP стек, който да си комуникира с web сървъра през socket или локален порт) и т.н. и т.н. По същество (въпреки че разработчиците на LSWE вероятно ще ми се обидят от такава аналогия), LiteSpeed прави същото за web стековете, което Docker прави за контейнерната виртуализация.

LiteSpeed и WordPress/WooCommerce

Ако се съсредоточим само върху връзката между LSWE и WordPress платформата, след инсталирането на нов сайт или мигриране на съществуващ такъв от друг хостинг доставчик, е необходимо да премахнете всички видове кеширащи и оптимиращи модули като W3 Total Cache, WP SuperCache, CometCache/RapidCache и спомагателни инструменти като Autoptimize, Fast Velocity Minify, Redis Object Cache или други, и да ги замените с официалния модул LiteSpeed Cache for WordPress (LSCWP).

След като направите това, ще се се озовете в един красив дашборд:

Панелът за управление на LSWE

Този панел служи за взаимодействие и с услугата QUIC.cloud, която ще коментирам най-накрая. Засега за нея е важно да знаете, че под „облачното“ си име тя крие два вида услуги: такива по оптимизиране на локалното съдържание, и CDN (Content Delivery Network) и че понеже е разработена от същата компания, която развива LSWE, двете услуги работят в пълна синергия, а наличието на LSWE лиценз ви дава право на безплатно ползване на услугите на QUIC.cloud в определен обем всеки месец.

Кеширане и управление на ресурсите

Авторите на кеширащи модули за WordPress (а и по-принцип) се сблъскват с два трудни за решение проблема.

(1) Техният софтуер трябва да може да функционира без оглед на сървърния стек под него (т.е. обичайно се поддържат и Apache, и Ngnix, както и различни видове добавъчни технологии като memcache/memcached, Redis, Varnish и т.н.)

(2) Трябва да се направи баланс между леснотата за настройка (за да могат и потребителите с минимални технически познания да могат да подкарат модула и да оставят 5-звезден рейтинг в библиотеката за разширения на WordPress, или поне да видят такъв ефект от него, че да си платят за настройка и поддръжка) и дълбочината на контрола (така че експертите да могат да се справят сами, без да счупят сайта след себе си).

Различните решения подхождат по коренно различен начин: достатъчно е само да сравним ноторно трудния за конфигуриране и невероятно богат като възможности W3 Total Cache с постния откъм потребителски контролируеми функции, но ефективен WP Super Cache.

В случая разработчиците и потребителите на LSCWP имат предимство: тъй като стекът е само един (LiteSpeed сървър), а не непредвидима чорба от технологии (различни версии на Apache/Ngnix, различни версии на PHP и различна комбинация от кеширащи модули като Redis), настройките за кеширане са сложни и многообразни, но са прекрасно документирани и идват с препоръчителни стойности. Разработчикът ви дава достъп до цялата функционалност на системата и гарантира, че ще можете да я управлявате правилно и добре; от вас зависи колко надълбоко ще задълбаете.

[1] Cache Control Settings

Ето как изглежда панелът за контролиране на кеша на LSWE в цялото му величие:

Панелът за контрол на кеширането на LSCWP

Впечатляващо, нали? И това е само началната страница на контолния панел за настройките на кеша. Имате още 8 панела с настройки: TTL, Purge, Excludes, ESI, Object, Browser, Advanced и WooCommerce. Няма да ви отегчавам с още картинки (ако съм си свършил работата, вероятно вече сте вдигнали виртуална машина и сте качили LSWE стек отгоре…), но ето техните функции накратко:

[2] TTL Settings

Оттук можете да зададете стойности в секунди за валидността на различни видове кеш:

  • Default Public Cache TTL: публично видими ресурси (такива, които се ползват от всички посетители)
  • Default Private Cache TTL: да, LSWE може да генерира кеширани страници само за индивидуална употреба — по този начин скоростта на достъп за логнати потребители също се увеличава, а сървърът се разтоварва. Онлайн магазините и други сайтове, които разчитат на динамично обновяване на информацията обикновено не кешират съдържание за логнатите си потребители, защото е трудно да се изолират данните и има риск да се сервират чужди данни. Със стека на LSWE и LSCWP това не е проблем, понеже всички компоненти на кеширането — съдържанието на обектния и файловия кеш и т.н. се контролират чрез сесиите, които се управляват от web сървъра.
  • Default Front Page TTL — самостоятелен контрол върху съдържанието на заглавната страница, която е възможно да се обновява с различно темпо спрямо останалите страници в сайта, например заглавна страница на новинарски сайт или електронен магазин по време на промоционална кампания
  • Default Feed TTL и Default REST TTL — самостоятелен контрол върху информацията, която сайтът подава чрез feed-ове или API към външни потребители
  • Default HTTP Status Code Page TTL — оттук можете да контролирате дали и как да кеширате страниците, които сървърът сервира при възникване на грешки с HTTP кодове например 403, 404 или 500, така че вашите посетители да не натоварват сървъра в проблемен момент, рефрешвайки нетърпеливо

[3] Purge Settings

Този панел е мислен страшно много. От него можете много прецизно да контролирате кога да инвалидирате кешираните обекти. Можете да задействате селективен purge на различни видове страници на WordPress (Auto Purge Rules For Publish/Update) в зависимост от това дали имат или нямат widget-и с динамично съдържание; можете да задействате purge при изпълнение на някой event hook (Purge All Hooks), тоест да инвалидирате кеша при настъпването на различни вътрешни и дори външни за сайта събития. На теория например може лесно да се направи така, че кешът да се освежава, когато ваш доставчик си обнови продуктовия feed, от който вие генерирате съдържание за страница с оферти. Можете да инвалидирате периодично кеш по списък (Scheduled Purge URLs и Scheduled Purge Time).

Ако сайтът има много посещения, инвалидирането на кеша може да доведе до неприемливо забавяне, понеже трябва изчислителна мощност за генериране на кеш от новото съдържание. Затова понякога има смисъл първо да генерирате новото съдържание и чак тогава да изпразните кеша, вместо обратното. Не съм виждал друг кеширащ модул за WordPress, който да предлага нещо подобно, но LSCWP има такава функция — Serve Stale. Чрез нея, подаването на остаряло съдържание да продължи дори след инвалидирането, докато новият ресурс е готов за сервиране. Найс, а?

[4] Excludes Settings

Оттук можете да задавате изключения, които да не се кешират. Можете да ги дефинирате чрез следните средства:

  • Do Not Cache URIs — гледа се съдържанието на сървърната променлива REQUEST_URI и се поддържа стандартния синтаксис, познат от писането на rewrite директиви (^ за начало, $ за край на стринг)
  • Do Not Cache Query Strings — описват се POST параметрите на заявки. Тоест, можете например да конфигурирате модула да ви показва прясно генерирана страница за всеки URL, като му долепите параметър ?cache=disabled (или някакъв nonce, дето само вие си го знаете…)
  • Do Not Cache Categories — оттук описвате категорните страници, които не искате да кеширате, използвайки името (не slug-а!) на съответната категория. Работи и за продуктовите категории на WooCommerce.
  • Do Not Cache Tags — същото, но за тагове.
  • Do Not Cache Cookies — тази опция ви позволява да генерирате бисквитка с определено съдържание и ако сървърът я прочете, ще ви генерира нова страница в отговор на всяка заявка, вместо да ви подаде кешираното копие. Тази функция вероятно има смисъл в някакви специфични ситуации (примерно, лимитирано по време специално съдържание, което се показва през определен URL и след това експирясва). И именно защото не е популярна, а екзотична функция, нейното наличие е още по-забележително.
  • Do Not Cache User Agents — точно това, което си мислите. Вкарайте Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Mobile/15E148 Safari/604.1 и ще накарате всички собственици на iPhone да си мислят, че телефоните им се забавят заради проблеми с батерията.
  • Do Not Cache Roles — можете да изключите кеширането според ролята на логнатия потребител.

[5] ESI Settings

Това, братя и сестри, е истинска технология от 21-ви век. ESI (Edge Site Includes) позволява да изтеглите страница от кеша и в последния момент преди да я сервирате на потребителя, да подмените някои фрагменти от нея с други фрагменти, които са кеширани с различно време на живот или дори не са кеширани.

Тези от вас, които използват шорт-кодове в WordPress, най-лесно ще разберат колко много възможности дава тази технология. Чрез шорт-кодове може в дадена страница да се вмъква динамично съдържание (например, в страница с обменни курсове да показваме курса на лева към еврото чрез шорт-код, който при всяко зареждане на страницата от посетител изпълнява заявка към сайта на БНБ и връща курса на момента. Чрез ESI ние можем да маркираме този шорт-код като динамичен и LSCWP ще сервира страницата от кеша, но ще покаже актуална стойност за обменния курс (напр. [shortcodeA forex="EUR"] става [ESI shortcodeA forex="EUR"]).

Между другото, интегрирането на ESI в WordPress/WooCommerce най-накрая приближава платформата до функционалността на Magento. Magento поддържа ESI механизъм ако не се лъжа още от времето на версия 1.9 (повече от 10 години). Именно поддръжката на ESI е една от причините Magento да е в състояние да функционира под огромно натоварване (милиони потребители месечно).

[6] Object Cache Settings

WordPress не е обектно-ориентирана система, но нейните компоненти се третират като обекти за различни цели, една от които е кеширането. Всяка страница (page) или публикация (post) в WordPress например се разглежда като обект. И затова обектният кеш е много полезен инструмент — чрез него, вместо всеки път страницата или публикацията да се асемблира наново от съставните си части чрез серия от заявки към базата данни, тя може да се асемблира веднъж и да се постави като индивидуален обект в обектния кеш, откъдето да се извиква за нуждите на системата.

Обектните кеширащи модули са два вида: volatile и persistent. В контекста на интернет хостинга, двата най-популярни кеширащи модули са Memcached (който е volatile — използва само оперативна памет и губи съдържанието си при рестарт на процеса) и Redis (който е persistent — използва и памет, и диск, и след рестарт си възстановява съдържанието).

Чрез панела Object на LSCWP можете да активирате кеширането на обекти. Модулът поддържа и Memcached, и Redis; документацията споменава и още една среда: LSMCD — базирана на Memcached кешираща система от авторите на LiteSpeed, която обаче е persistent като Redis, може да оперира в High Availability режим (ако една инстанция отпадне, услугата като цяло ще продължи да работи) и поддържа разделяне на кеша на ниво потребител с цел защита на данните. LSMCD не беше инсталиран на сървъра, на който мигрирах сайта на моя клиент, но избрах Redis и той се интегрира безпроблемно.

[7] Browser Cache Settings

Оттук се контролира най-простата и скучна част от кеширането: възможността за управление на това как се кешира статичното съдържание в браузера на потребителя. Единствените две настройки са включено/изключено и времето на живот на браузерния кеш. Въпреки това ролята на този панел не е за подценяване — докато работите върху своя сайт, е силно препоръчително да държите тази опция изключена, понеже се очаква често да променяте съдържанието, което ще подавате към клиентите. Чак когато сайтът придобие завършен вид, тогава я активирайте.

[8] Advanced Settings

В този панел са събрани три функции, които нямат нищо общо помежду си, но няма и как да бъдат поместени в другите панели на LSCWP.

Login Cookie позволява да се генерират бисквитки, различни за отделните web приложения (сайтове), които се изпълняват от един и същ домейн, които следят дали потребителят е логнат в него или не.

Ако се питате каква полза има от това, ще ви дам пример. Когато работя с моите клиенти, обичайно поддържам развойно (staging) копие и продукционно копие на един и същ сайт. На staging копието тествам нови версии на плъгини, теми и т.н., провеждам обучение на клиента или т.н., и след това му го оставям да си го ползва като тестова площадка.

Чрез задаването на различни идентификатори на бисквитките ние можем да контролираме дали потребителят е логнат на продукционния или staging сайта. позволява да се генерират бисквитки, различни за отделните web приложения (сайтове), които се изпълняват от един и същ домейн, които следят дали потребителят е логнат в него или не.

Improve HTTP/HTTPS Compatibility помага в случаите, когато домейнът има смесено съдържание (HTTP и HTTPS). Ако обаче имате такъв проблем, е най-добре да го разрешите, като преминете изцяло на HTTPS, отколкото да го заобикаляте през кеширащия модул!

Instant Click работи на същия принцип като модула Flying Pages на известния WP оптимизатор и изключително талантлив програмист Gijo Varghese. Тази функция разчита на особеностите на мисловния и двигателен процес на интернет потребителите.

Често пъти, докато разглеждаме дадена страница, ние си помагаме с курсора на мишката. Някои наблюдателни хора са забелязали, че обикновено при стигането до някой линк има известен интервал от време между вземането на решение и самото кликване. През това време курсорът на мишката сочи линка към страницата (вместо да продължава да се движи по страницата) и ако това задържане превиши определен интервал (примерно 20ms), малък JavaScript изпраща заявка към браузера да зареди предварително съдържанието на този линк.

Това спекулативно зареждане на следващата страница създава субективното усещане, че новата страница се е заредила много бързо. Недостатъкът на тази функция е, че тя има потенциала да затрупа сървъра с много излишни заявки. Затова трябва да се използва внимателно и само ако разполагате с достатъчен ресурс да оберете локален пик в заявките. Просто правило: не активирайте Instant Click на сървър с 15-минутен load average над 60-70%!

WooCommerce Settings 

Един от основните проблеми с кеширането на онлайн магазини е проблемът с наличностите. Ако от даден продукт е останала само 1 бройка и някой го поръча, докога останалите потребители ще виждат съобщение „В наличност“ и активен бутон за добавяне към кошницата? Поради тази особеност често пъти администраторите на сайтовете на онлайн магазини не реализират пълноценно кеширане на продуктовите и категорни страници, а настройват своите сървъри да кешират само статичните ресурси (CSS, JS, изображения) в браузера на потребителя. Резултатът от това са по-бавни и натоварени сайтове, в които всяка продуктова страница се асемблира наново, преди да бъде изпратена към посетителя.

Тъй като е много добре интегриран с платформата, LSCWP може да се вклини в схемата от събития на WordPress и да реагира със селективно инвалидиране на кеша за продуктовите и категорни страници. Първата опция в панела WooCommerce Settings е кръстена Product Update Interval и нейната задача е да предостави избор измежду четири ситуации, при които да се изчисти кешът на продуктовите и категорни страници.

Коя настройка е най-добре да изберете зависи от това как работи вашият магазин. Ако продуктовите страници показват наличното количество от даден продукт („3 бр. в наличност“) или имат индикатор за оставащо количество (напр. зелена точка за „в наличност“, жълта точка за „последни бройки“, оранжева точка за „остава само 1 брой“), тогава е добре да инвалидирате кеша на тази страница след всяка поръчка.

Ако обаче съдържанието на страницата превключва само между състояния „в наличност“ и „извън наличност“, тогава няма смисъл да инвалидирате кеша при всяка поръчка, а само когато продуктът се изчерпа. По подобен начин трябва да прецените какво да се случва и с категорните страници при промяна на количеството или статуса за наличност на продукт от съответната категория.

  • Purge product on changes to the quantity or stock status. Purge categories only when stock status changes — продуктовата страница се инвалидира при промяна на наличността и/или статуса на наличност; категорната страница се инвалидира само при промяна на статуса на наличност на продукта.
  • Purge product and categories only when the stock status changes — и продуктовата, и категорната страница се инвалидират само когато продуктът се изчерпа, или отново влезе в наличност.
  • Purge product only when the stock status changes. Do not purge categories on changes to the quantity or stock status — продуктовата страница се инвалидира само когато продуктът се изчерпа; категорната страница не се инвалидира. Тази настройка е подходяща при наличието на категорни страници без Quick View/Quick Order функционалност, и особено ако съдържат много продукти. Тъй като не показват статуса на продукта, а само служат за навигиране между продуктите в дадена категория, този тип страници няма нужда да се обновяват дори когато даден продукт си промени състоянието на наличност, а и инвалидирането на такива сложни по състав страници отнема много процесорно време.
  • Always purge both product and categories on changes to the quantity or stock status — Пуцай, куме! Продуктовата и категорните страници се обновяват при всяка промяна на количествата и/или статуса на наличност. Използвайте тази мярка внимателно, особено ако имате „дълбоки“ категории с много продукти.

Use Front Page TTL for the Shop Page служи да определи как да се третира заглавната страница на магазина. Потребителите на WooCommerce знаят, че платформата може да прави разлика между „заглавна страница“ на сайта и „заглавна страница на магазина“ — следствие от факта, че WordPress е CMS система много преди да почне да се използва и за e-commerce платформа.

Заглавната страница на магазина е много важна поради няколко причини: на нея често се публикува информация с временен характер (промоционални оферти, продукти за продажба с ограничена наличност и т.н.) и затова има необходимост тя да се обновява относително често. От друга страна, тази страница получава много входящ трафик, което пък е стимул да я държите кеширана и да инвалидирате кеша максимално рядко, за да пазите сървъра от претоварване.

Интересното е, че самата функция не е добре документирана. Пише само, че ако е установена на „включено“, стойността на TTL за заглавната страница на магазина ще бъде същата като за заглавната страница на сайта (която се задава в панела [2] TTL). Не е посочено обаче какво се случва, ако функцията е изключена. Дали тогава заглавната страница на магазина ще се третира като категорна страница и ще се инвалидира споре логиката на Product Update Interval настройката? Не е ясно. Мисля си да питам поддръжката на LSCWP да видим какво ще кажат и ако ми отговорят, ще допиша този текст.

Последната функция в панела WooCommerce Settings е Privately Cache Cart — дали да кеширате съдържанието на количката за индивидуалните потребители. Няма какво да се чудите: активирайте тази функция! Клиентите, които разглеждат вашия онлайн магазин продължително и слагат и махат множество продукти в количката си, ще ви бъдат благодарни, понеже сайтът няма да изпълнява непрекъснато заявки чрез AJAX, за да се допитва до сървъра за съдържанието на своята кошница при всяко зареждане на нова страница.

Какво да правите оттук насетне с LiteSpeed Cache?

За да тествате дали сте настроили правилно модула и дали кеширането работи, можете да отворите сайта check.lscache.io и да му подадете URL към произволна страница от вашия сайт. Ако всичко е настроено както трябва, трябва да видите това съобщение:

И когато може би си мислите, че това е всичко и се чувствате възнаградени, че прочетохте докрай тази обширна статия, бързам да ви кажа — това далеч не е краят на описанието на функциите, които LiteSpeed Cache за WordPress ви предоставя! Тепърва имам да ви разкажа за оптимизирането на изображенията, за оптимизирането на страници, за оптимизирането на базата данни на сайта, за функцията за обхождане на сайтове от LiteSpeed сървъра, и за допълнителните инструменти. И не забравяйте, че все още не сме разгледали в детайли услугата QUIC.cloud!

Този текст наистина стана далеч по-дълъг, отколкото очаквах, затова всичко останало ще бъде публикувано в отделен блог пост в близко бъдеще. Ако тази статия ви харесва, споделете я във Facebook или Twitter! Ако пък искате да мигрирате своя бавен WooCommerce сайт на бърз хостинг с LiteSpeed Enterprise сървър и да го интегрирате със CDN услугата на QUIC.cloud — свържете се с мен. Времето за миграция зависи от големината на сайта: мигрирането на WooCommerce магазин с около 100 хил. файла с общ обем около 10 GB (файлове и бази данни) отнема около 3 часа, и може да се направи без самият сайт да спре да работи.

АКО НАПИСАНОТО ВИ ДОПАДА…

Абонирайте се за моя блог!

Ще получавате съобщение, когато публикувам нова статия. Можете да се отпишете по всяко време.

Email адрес

Подобни статии