-
Notifications
You must be signed in to change notification settings - Fork 0
/
Varnish-Cache-dla-miekkich-form-inteligencji.html
12 lines (11 loc) · 18.1 KB
/
Varnish-Cache-dla-miekkich-form-inteligencji.html
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html> <html lang="pl"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Varnish Cache dla miękkich form inteligencji · Rafal Makara</title> <meta property="og:title" content=" Varnish Cache dla miękkich form inteligencji "> <meta property="twitter:title" content=" Varnish Cache dla miękkich form inteligencji "> <meta property="og:description" content=" W dobie gdy wszyscy stają się ludźmi Pi, a product engineering zyskuje na popularności ponad software development manadżerowie są zmuszeni rozumieć aspekty techniczne wytwarzanych rozwiązań. Czym są warstwy cachujące oraz reverse proxy? W ludzkich słowach przybliżam temat. "> <meta name="twitter:card" content="summary" /> <meta name="twitter:site" content="@rafalmakara" /> <meta property="og:image" content="https://rmakara.github.io/assets/20180129_header.jpg" /> <meta name="twitter:image" content="https://rmakara.github.io/assets/20180129_header.jpg" /> <meta name="description" content="Wdrożenie z miękkiej perspektywy"> <link rel="icon" href="https://rmakara.github.io//assets/favicon.ico"> <link rel="apple-touch-icon" href="https://rmakara.github.io//assets/apple-touch-icon.png"> <link rel="stylesheet" href="https://rmakara.github.io//assets/core.css"> <link rel="canonical" href="https://rmakara.github.io//Varnish-Cache-dla-miekkich-form-inteligencji"> <link rel="alternate" type="application/atom+xml" title="Rafal Makara" href="https://rmakara.github.io/feed.xml" /> </head> <body> <aside class="logo"> <a href="https://rmakara.github.io//"> <img src="https://avatars0.githubusercontent.com/u/1880231?v=4" class="logo-avatar"> </a> <span class="logo-prompt code">Back to Home</span> </aside> <aside> <p class="goodbye"> This blog is no longer maintained <br/><br/> Subscribe to new articles at <a href="https://www.sorryengineering.com/">https://www.sorryengineering.com/</a> </p> </aside> <p class="menu"> <br /><br /> <a href="/">EN Articles</a> | <a href="/pl">PL Articles</a> <br /> <a href="/about">About me</a> | <a href="/help">How can I help?</a> | <a href="https://www.linkedin.com/in/rafalmakara/">My LinkedIn Profile</a> </p> <div id="content"> <article> <div class="divider"></div> <div class="center"> <a class="prev" href="/Ksiazki-i-najlepszy-prezent-materialny-w-2017">Previous article - Książki i najlepszy prezent materialny w 2017</a> </div> <div class="divider"></div> <h1 class="title">Varnish Cache dla miękkich form inteligencji</h1> <div class="center"> <time class="code">2018-01-29</time> </div> <div class="divider"></div> <h1 id="wdrożenie-z-miękkiej-perspektywy">Wdrożenie z miękkiej perspektywy</h1> <p>Nigdy nie miałem okazji wdrażać Varnisha (ani innego web acceleratora czy reverse proxy) siedząc bezpośrednio przy kodzie. Jednak w ostatnim czasie przeszedłem przez cały proces implementacji rozwiązania z punktu widzenia project managera. Słownictwo wykorzystywane przez programistów podczas prac nad Varnishem zazwyczaj jest bardzo wysokopoziomowe, ponieważ zakłada, że menadżer i tak nie zrozumie szczegółów rozwiązania lub wręcz przeciwnie - jest bardzo techniczne i wtedy rzeczywiście PM nic z tego nie rozumie.</p> <p>Poniższy artykuł ma na celu wyjaśnienie podstawowych pojęć związanych z Varnishem, aby osoby niebędące specialistami w tym zakresie były w stanie zrozumieć, o czym mówią programiści.</p> <h1 id="web-accelerator-czy-reverse-proxy">Web accelerator czy Reverse proxy?</h1> <p>Varnish jest zazwyczaj nazywany web acceleratorem lub reverse proxy. Skąd pochodzą te nazwy? Akceleracja sugeruje, że głównym zadaniem narzędzia jest przyśpieszanie działania strony. W najprostszym rozumieniu działania Varnisha można tak go określić. Varnish tworzy warstwę stojącą między użytkownikiem i serwerem aplikacyjnym (dla uproszczenia załóżmy, że mamy do czynienia z aplikacją monolityczną uruchomioną na jednym serwerze aplikacyjnym), i jego głównym zadaniem jest redukowanie obciążenia aplikacji przez cacheowanie powtarzalnych żądań, które następnie będzie można serwować użytkownikom bez odwoływania się do serwera aplikacyjnego.</p> <p>Poza mechanizmem cacheowania dostarcza on szersze rozwiązania jak np. load balancing. Na potrzeby tego artykułu skupimy się jednak głównie na cache.</p> <p>Aby zrozumieć pojęcie reverse proxy wyjaśnijmy w uproszczeniu, czym jest serwer proxy. Wyobraźmy sobie, że jesteśmy użytkownikiem Internetu, który chce włamać się na stronę banku internetowego. W celu ukrycia swojej tożsamości korzystamy z serwera proxy, który będzie pośredniczył w ruchu między nami i bankiem. Dzięki wykorzystaniu takiego pośrednika można powiedzieć, że “chowamy się” za nim i z punktu widzenia ofiary (banku) to serwer proxy włamuje się do banku, a nie my. Wysyłane przez nas żądanie trafia do serwera proxy, następnie do banku, odpowiedź zwracana jest do serwera proxy i na końcu do nas.</p> <p>Reverse proxy to podobny mechanizm, ale stojący po drugiej stronie płotu. W tym wypadku to serwer (a nie użytkownik) “chowa się” za serwerem reverse proxy, który symuluje jego zachowanie. Z perspektywy użytkownika wysyłamy żądanie do naszej aplikacji, które tak naprawdę trafia do serwera reverse proxy. Ten serwer decyduje czy odpowie nam samodzielnie, czy przekaże nasze zapytanie do prawdziwego serwera aplikacyjnego.</p> <h1 id="podstawowa-zasada-działania-cache-w-varnishu">Podstawowa zasada działania cache w Varnishu</h1> <p>Proces wygląda następująco:</p> <ul> <li>Użytkownik wchodzi na stronę internetową.</li> <li>Żądanie HTTP trafia do Varnisha: <ul> <li>Jeżeli Varnish posiada aktualny cache elementu, o który jest proszony to odsyła response użytkownikowi.</li> <li>Jeżeli Varnish nie posiada aktualnego cache elementu to przekazuje request do serwera aplikacyjnego i w dalszej kolejności zwraca odpowiedź użytkownikowi na podstawie danych otrzymanych od serwera aplikacyjnego.</li> </ul> </li> </ul> <h1 id="vcl-varnish-configuration-language">VCL, Varnish Configuration Language</h1> <p>Językiem, w którym tworzymy konfigurację Varnisha jest VCL. W rozmowach z programistami określenie VCL często jest skrótem myślowym do określenia pliku konfiguracyjnego Varnisha. VCL pozwala nam na dostosowanie narzędzia do naszych potrzeb.</p> <h1 id="czas-ważności-ttl-i-typ-cache">Czas ważności (TTL) i typ cache</h1> <p>Podstawowym podziałem cacheowanych w Varnishu elementów jest rozdzielenie contentu statycznego od dynamicznego. Przykładem contentu statycznego może być logo firmy, które zazwyczaj jest niezmienne. Przykładem contentu dynamicznego może być wielkie zdjęcie obrazujące stan magazynowy towaru w sklepie internetowym, które jest aktualizowane co 30 minut.</p> <p>Dla dwóch powyższych typów zawartości strony możemy zdefiniować czasy TTL (time-to-live), które określą czas ważności cache liczony od momentu jego utworzenia. Przykładowo, określamy TTL na 60 minut. Jeżeli wejdziemy na stronę internetową to bazując na naszej wizycie jej cache zostanie stworzony w Varnishu i wszyscy kolejni użytkownicy wchodzący na tą samą stronę w ciągu najbliższych 60 minut otrzymają zawartość strony bardzo szybko, ponieważ odpowiedź zostanie przygotowana w warstwie reverse proxy, bez wykorzystania serwera aplikacyjnego. Umożliwia nam to bardzo szybkie pokazanie strony internetowej użytkownikowi, ale generuje ryzyko, że w ciągu tych 60 minut strona w serwerze aplikacyjnym zostanie zaktualizowana - wtedy użytkownicy będą otrzymywać nieaktualną wersję strony, aż do zakończenia czasu TTL.</p> <p>Parametrem mówiącym o wieku danego elementu cache jest Age, który przedstawia nam wartość w postaci ilości sekund - od chwili utworzenia cache, do teraz. Gdy Age zrówna się z TTL - cache uznawany jest za nieaktualny.</p> <h1 id="grace-time">Grace Time</h1> <p>Czas “ważności” cache można w awaryjnych sytuacjach wydłużyć. Varnish od wersji 4 pozwala na zdefiniowanie tak zwanego czasu Grace Time. Określa on czas ponad TTL w ciągu którego możemy pogodzić się z odpowiedzią użytkownikowi nieaktualną zcacheowaną wersją strony, gdy napotkamy problem z uzyskaniem odpowiedzi od serwera aplikacyjnego.</p> <p>Przykładem zastosowania grace time może być sytuacja, w której czas ważności cache konkretnej strony minął, użytkownik przesyła request o daną stronę, z poziomu Varnisha okazuje się że serwer aplikacyjny jest niedostępny lub bardzo obciążony, Varnish sprawdza grace time danego elementu i jeżeli konfiguracja pozwala nam na pogodzenie się z faktem nieaktualnej odpowiedzi to Varnish odpowiada użytkownikowi.</p> <p>Równolegle do przeprowadzania tej operacji, Varnish jest w stanie zainicjować proces odświeżający pamięć podręczną danego elementu, aby została ona zaktualizowana w osobnym wątku na potrzeby przyszłych użytkowników.</p> <h1 id="health-check">Health check</h1> <p>W celu określenia wydajności działania backendu oraz podjęcia decyzji o wykorzystaniu grace time Varnish pozwala na wykonywanie health checków. Sposób ich działania jest samoopisujący się przez poniższy kod pochodzący z dokumentacji Varnisha.</p> <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>backend server1 {
.host = "server1.example.com";
.probe = {
.url = "/";
.interval = 5s;
.timeout = 1 s;
.window = 5;
.threshold = 3;
}
}
</code></pre></div></div> <h1 id="automat-skończony-finite-state-machine">Automat skończony (finite state machine)</h1> <p>W celu rozwiązania wcześniej przedstawionego problemu możliwej nieaktualności pamięci podręcznej musimy zrozumieć stany, jakie występują w Varnishu, który bywa nazywany skończoną maszyną stanów / automatem skończonym / finite state machine.</p> <p>Stany można rozumieć jako sposób obsłużenia danego żądania HTTP, które trafia do Varnisha. Podstawowe z nich to:</p> <ul> <li><code class="language-plaintext highlighter-rouge">miss</code> - Żądanie od użytkownika przechodząc przez Varnish szukało i nie znalazło zcacheowanej wersji elementu, którego potrzebowało. W takiej sytuacji konieczne jest odwołanie się do z aplikacji.</li> <li><code class="language-plaintext highlighter-rouge">pass</code> - Żądanie nie szukało wersji zcacheowanej, a jedynie “przeszło” przez Varnisha prosto do aplikacji. W momencie zwracania odpowiedzi również nie jest ono cacheowane.</li> <li><code class="language-plaintext highlighter-rouge">hit</code> - Żądanie znalazło aktualny cache w Varnishu. Pobiera element z cache i zwraca odpowiedź użytkownikowi. Nie obciąża aplikacji.</li> <li><code class="language-plaintext highlighter-rouge">hit_for_pass</code> - Typ akcji, który mówi o tym, że Varnish to nie tylko warstwa cache, a także mądre oprogramowanie stanowiące firewall stojący przed aplikacją. <code class="language-plaintext highlighter-rouge">hit_for_pass</code> to działanie, przy którym w cache nie znajduje się zcacheowany obiekt i inicjuje ono pobranie go z aplikacji. Oznacza jednak dane żądanie jako “w trakcie pobierania” i dzięki temu inni użytkownicy aplikacji, którzy zapytają o to samo nie generują kolejnych żądań odwołania do backendu, a czekają w warstwie reverse proxy, aż to jedno dojdzie z aplikacji do Varnisha. Dzięki temu, w przypadku 1000 użytkowników pytających o to samo przekazujemy 1 żądanie do aplikacji, 999 żądań czeka w Varnishu. Gdy odpowiedź wróci do Varnisha z backendu - otrzyma ją 1000 użytkowników.</li> <li><code class="language-plaintext highlighter-rouge">waiting</code> - Akcja określająca, że żądanie użytkownika czeka na aktualizację wynikającą z innego żądania <code class="language-plaintext highlighter-rouge">hit_for_pass</code>.</li> </ul> <p>Kompletną listę stanów i wyjaśnienie ich działania warto przestudiować w rozdziałach <a href="https://book.varnish-software.com/4.0/chapters/VCL_Basics.html">VCL Basics</a> oraz <a href="https://varnish-cache.org/docs/trunk/users-guide/vcl-built-in-subs.html.">Build in subroutines</a> zawartych w oficjalnej dokumentacji.</p> <h1 id="inwalidacja-cache">Inwalidacja cache</h1> <blockquote> <p>There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors.</p> <p>– Phil Karlton (edited by: Leon Bambrick)</p> </blockquote> <p>Większość systemów nie opiera się jedynie na samym odczytywaniu danych, a pozwala dodatkowo na ich modyfikację. Programista implementujący rozwiązanie jest w stanie wyznaczyć operacje, które powinny natychmiastowo wymuszać wyczyszczenie cache. Przykładem może być aktualizacja nazwy produktu w sklepie internetowym. Załóżmy, że nasza strona produktowa jest na tyle niezmienna, że cacheujemy ją w pełni. Pewnego dnia, administrator sklepu aktualizuje nazwę produktu. W związku z tym, użytkownicy wchodzący na omawianą stronę powinni zobaczyć jego nową nazwę. W tym celu programista po zapisaniu produktu w panelu administracyjnym może wyczyścić dane elementy cache omawianej strony produktowej i tym samym wymusić załadowanie nowej zawartości strony wprost z serwera aplikacyjnego.</p> <p>Do przeprowadzania powyższych operacji korzystamy z dwóch typów żądań. Pierwsze z nich to <code class="language-plaintext highlighter-rouge">purge</code>, który pozwala nam na wyczyszczenie pamięci podręcznej konkretnego adresu URL / elementu. Wywoływany jest on podobnie do typowych requestów HTTP GET. Drugim typem żądania jest <code class="language-plaintext highlighter-rouge">ban</code>, który na podstawie wskazanego wyrażenia regularnego może nam pomóc z wyczyszczeniem cache wielu stron / elementów. Ban może również zostać wywołany podobnie do requestu HTTP, ale domyślnym momentem jego uruchamiania jest moment trafienia w cache (<code class="language-plaintext highlighter-rouge">hit</code>).</p> <h1 id="edge-side-includes">Edge Side Includes</h1> <p>W celu zoptymalizowania procesu inwalidacji cache możemy wykorzystać mechanizm ESI. Pozwala on na wyznaczenie w obrębie strony konkretnych elementów, które nie powinny być cacheowane. Przykładowo, decydujemy się trzymać w cache całą stronę karty produktu, ale zauważamy na niej dwa elementy, które często się zmieniają - cena oraz stan magazynowy. Te dwa elementy możemy otoczyć blokami ESI. Doprowadzi to do sytuacji, w której będziemy mieli zachowaną w pamięci podręcznej całą stronę, a o te dwa wskazane elementy każdorazowo będziemy odpytywać serwer aplikacyjny - dzięki temu one zawsze będa aktualne, a pozostała zawartość strony będzie ładować się bardzo szybko. W efekcie nie musimy inwalidować cache tej strony.</p> <h1 id="monitorowanie-efektów">Monitorowanie efektów</h1> <p>Po wdrożeniu Varnisha z pewnością chcielibyśmy zmierzyć efekty płynące z faktu jego zaimplementowania. Należy pamiętać, że popularne oprogramowania monitorujące lub profilujące (jak np. New Relic) są spięte zazwyczaj z serwerem aplikacyjnym. Przykładowo, w przypadku pracy z językiem PHP nasze oprogramowanie może analizować pracę PHP-FPM. Varnish znajduje na warstwie bliższej użytkownikowi, w związku z czym nie zaobserwujemy efektów jego pracy w New Relicu, a dostrzeżemy jedynie zmniejszony ruch na serwerze aplikacyjnym.</p> <p>Efekty pracy Varnisha możemy zaobserwować np. przez cykliczne uruchamianie testów symulujących klikanie użytkownika internetowej według wskazanych scenariuszy. Przez wyciągnięcie czasów średnich ładowania poszczególnych stron w okresie przed i po wdrożeniu Varnisha powinniśmy móc zauważyć różnicę.</p> <h1 id="podsumowanie">Podsumowanie</h1> <p>Reverse proxy nie takie straszne jak je malują. Dzięki tego typu narzędziom możemy przyśpieszyć działanie strony internetowej i poprawić doświadczenia użytkowników. To wszystko przy dość niewielkim koszcie wdrożenia. W skrajnych przypadkach możemy wykorzystać tego typu rozwiązanie do zamaskowania niewydolności backendu spowodowanej naszymi własnymi błedami… wróć… błędami tych legendarnych, innych programistów (sic!).</p> <p>Oryginalna dokumentacja Varnisha została napisana w bardzo przyjazny sposób i w pełni zachęcam do jej lektury.</p> <hr /> <h4 id="źródła-i-pojęcia">Źródła i pojęcia</h4> <ul> <li>[1] <a href="https://varnish-cache.org/docs/trunk/index.html">Varnish Documentation, https:/varnish-cache.com</a></li> <li>[2] <a href="https://book.varnish-software.com/4.0/chapters/VCL_Basics.html">VCL Basics, https://book.varnish-software.com</a></li> <li>[3] <a href="https://varnish-cache.org/docs/trunk/users-guide/vcl-built-in-subs.html">Built in subroutines, https:/varnish-cache.com</a></li> <li>[4] <a href="http://varnish-cache.org/trac/wiki/VCLExampleGrace">Grace, https:/varnish-cache.com</a></li> <li>[5] <a href="https://varnish-cache.org/docs/3.0/tutorial/purging.html">Purging & banning, https:/varnish-cache.com</a></li> </ul> </article> <div class="divider"></div> <div class="page-navigation code"> <a class="home" href="https://rmakara.github.io//" title="Back to Home">Back to Home</a> <br/><br/> <a class="next" href="/Event-Storming-Warsztaty-Agile-Wroclaw">Next article: Event Storming: Warsztaty Agile Wrocław</a> </div> </div> <br/> <aside> <p class="goodbye"> This blog is no longer maintained <br/><br/> Subscribe to new articles at <a href="https://www.sorryengineering.com/">https://www.sorryengineering.com/</a> </p> </aside> <div class="footer"> <span class="block">© 2023 Rafal Makara</span> <span class="block"><small></> Powered by <a href="https://jekyllrb.com/">Jekyll</a> and <a href="https://github.com/heiswayi/the-plain">The Plain theme</a>.</small></span> </div> </body> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-92815270-1', 'auto'); ga('send', 'pageview'); </script> </html>