post-images/what-is-varnish-and-how-does-it-work/cover.jpg

Varnish nedir, nasıl çalışır?

Varnish web sitelerini hızlandırmak için kullanılan bir HTTP reverse proxy’dir. Reverse proxy, istemcilere asıl sunucu gibi görünen bir ara sunucudur. Varnish web sayfalarını önbellekte (ram veya dosya) tutarak, istemci istek yaptığında eğer cevap önceden istenmişse aynı cevabı dönerek asıl sunucuya gitmeden ziyaretçiye cevap verir. Bu sayede veritabanı işlemleri, backend istekleri, 3rd party istekler gibi sunucuyu yoran veya zaman alan durumlar azalmış olur.

Ziyaretçileri her ziyarette tekrar oluşturulan dinamik sayfalar yerine önbelleğine alınmış statik sayfalara yönlendirir ve sitenin hızlı bir şekilde açılmasını sağlamış olur.

Yoğun trafik alan ve içerisinde barındırdığı verileri veritabanından çeken bir sayfamız olduğunu varsayalım. Her bir veritabanı işlemi kendi başına bir süreç işletir. Bir süre sonra bu durum sunucu tarafında bandwidth kullanımını arttıracaktır. Buna paralel olarak RAM ve CPU oranları da artacağından web sunucusunun cevap verme süresi de artacaktır ve sonuç olarak cevap veremez hale gelecektir. Varnish tam da bu noktada bizlere yardımcı oluyor. Nasıl mı? Bahsi geçen yoğunlukta trafik ve işlem yükümüz devam ediyor olsun. Bu sayfa görüntülenmek istendiğinde; Varnish, belleğinde olmadığı için isteği sunucuya iletir. Sunucu bir cevap döner. Dönen bu cevap belirlenen süre boyunca önbellek(cache)’de tutulur. Aynı istek önceden belirlediğimiz süre boyunca hangi kullanıcı olursa olsun veritabanı üzerinden değil de önbelleğe alınan varnish katmanı üzerinden cevap vermeye devam edecektir. Süre sonlandığında yani varnish önbelleğinde veri bulunmadığı durumda (invalid) sunucudan tekrar talep eder.

Dakikada 1.000 istek alan bir sayfada cache süresi 1 dakika belirlenmişse sunucu sadece 1.000 yerine 1 istek ile uğraşmış olacaktır.

VCL (Varnish Configuration Language)

Varnish, VCL(Varnish Configuration Language) olarak adlandırılan konfigürasyon dilini kullanır. Varnish’e VCL aracılığıyla HTTP trafiğinizi nasıl işleyeceğinizi aktarmış olursunuz. Gelen isteklerin hangi kurala göre cacheleneceği, bu cache’in ne kadar süreceği ve nasıl invalide edileceğini belirleyen metotlar barındırır.

Her gelen talep Varnish üzerinden akar ve VCL kodunu değiştirerek talebin nasıl işleneceğini etkileyebilirsiniz. Belirli istekleri belirlenen servise yönlendirebilirsiniz. Varnish’in istek veya yanıt üzerinde çeşitli eylemler gerçekleştirmesini sağlayabilirsiniz. Bu durumlar, Varnish’i sadece önbelleğe almak için kullanılan bir araç değil, son derece güçlü bir HTTP işlemcisi yapar.

Bu konfigürasyon dosyası C koduna çevrilir ve derlenerek binary dosyasına dönüşür. Bu sayede Varnish çok daha hızlı çalışır. Ayrıca VCL dosyası içinde C kodu direkt olarak da kullanılabilir.

VCL dosyaları alt yordamlar (subroutines) halinde düzenlenmiştir. Farklı alt yordamlar farklı zamanlarda yürütülür. Örneğin; Biri isteği aldığımızda, diğeri backend sunucusundan dosyalar getirildiğinde yürütülür.

VCL Syntax, subroutines, actions ve diğer pek çok özellik için VCL Dokümanını inceleyebilirsiniz.

Varnish vs Memcached

  • Memcached nedir? Yüksek performanslı, dağıtık, bellek içi bir veri deposudur. Memcached, veritabanı çağrıları, API çağrıları veya sayfa oluşturma sonuçlarından elde edilen küçük rastgele veri yığınları (dizeler, nesneler) için bir bellek içi anahtar-değer deposudur. Bu, Memcached’i daha hızlı hale getirecek, ancak aynı zamanda depolanması için bellek ayırmayı da gerektirecektir. Memcached’in dağıtık (distributed) olması birden çok sunucuda çalıştığı anlamına gelir. Uygulamanın sunucu katmanında, bellekte yer alır.

Hızlı nesne önbelleği (Fast object cache), Yüksek performans (High-performance), Kararlı (Stable)

  • Varnish nedir? Yüksek performanslı HTTP hızlandırıcı. Varnish Cache, HTTP isteklerini reverse proxy ile önbelleğe alan bir web uygulaması hızlandırıcısıdır. HTTP iletişim kuran bir sunucunun önüne kurulur ve içeriği önbelleğe alacak şekilde yapılandırılır. Muadillerine göre gayet hızlıdır. Mimarinize bağlı olarak, genellikle 300–1000x faktörü ile aktarımı hızlandırır. Sunucu katmanı içerisine girmez. Varnish web sunucusunun önündedir; önbelleğe alan bir reverse http proxy’si olarak çalışır. Reverse proxy kısmı, uygulamanız ile dış dünya arasında yer aldığı anlamına gelir.

Hızlı nesne önbelleği (Fast object cache), Çok Hızlı (Very Fast), Çok kararlı (Very Stable)

Genel olarak, Varnish kimliği doğrulanmamış (cookie ile gelen) trafik için çalışır ve memcached, kimliği doğrulanmış trafiği önbelleğe alır. Bu yüzden ikisi birlikte kullanılabilir.

Kurulum

Ubuntu/Debian kullanıcıları:

sudo apt-get install varnish

ile basitçe kurabilir. Varnish ön tanımlı olarak 6081 portunu dinler. Bunun 80. portu dinlemesini isterseniz /etc/default/varnish dosyasındaki “DAEMON_OPTS” direktifini değiştirebilirsiniz.

Varnish’in ön tanımlı ayar dosyası da /etc/varnish/default.vcl adresinde bulunur. Burada da ön tanımlı olarak 8080 portunda çalışan “backend”den verileri alacak şekilde tasarlanmıştır. Siz web sunucunuzu 8080 portu üzerinden çalıştırıp, yukarıdaki DAEMON_OPTS’dan da varnish’i 80. porttan çalışması için ayarlarsanız artık sunucunuza gelen istekler önce Varnish’e gelecek, orada eğer cache bulunamazsa web sunucunuza (backend) inecek.

Varnish ayarları, VCL(Varnish Configuration Language) ile tanımlanır. VCL ile ayar dosyalarında, kullanılacak backend’ler, bu backend’lere gidecek yükü dağıtacak director’lar, gelen isteklerin hangi kurallara göre cache’leneceği, bu cache’in nasıl invalide edileceği gibi şeyleri belirleyen methotlar bulunuyor. Bizim senaryomuzda vcl_recv ve vcl_fetch methodları içinde tanımlamalarımızı yapacağız.

Aşağıdaki VCL File içerisinde ki bu yapılandırmadan sonra varnish, “X-Requested-With” header’ı olmayan (Bizim belirlediğimiz koşul.) tüm istekleri 300s boyunca cache’lemeye başlayacak.

# istekler,8080.portta çalışan web sunucumuza gidecek  
backend default {  
    .host="127.0.0.1";  
    .port="8080";  
}

# istek başlangıcında çağırılır  
# burada,istek manipule edilebilir,  
# örneğin:isteğe bir header eklenebilir  
sub vcl\_recv{

    # AJAX istekleri cache'lenmesin,  
    # çoğu kütüphane böyle bir başlık ekler  
    # eğer bu başlık varsa,cache'leme  
    if(req.http.X-Requested-With){  
        return(pass);  
    }

    # geri kalan tum istekler cache'lensin  
    return(lookup);  
}

# istek,backend'den fetch edildiğinde çağırılır  
sub vcl\_fetch{

    # 200 dönuyorsa,icerik 300 saniye boyunca cache'lensin  
    if(beresp.status==200){  
        set beresp.ttl=300 s;  
        return(deliver);  
    }  
}

Uygulama

Basit bir Spring Boot uygulaması ile her atılan isteğin yaklaşık 5sn sürdüğü bir ortam oluşturuyoruz (Thread.sleep(5000)). (Yorucu bir sistem gibi görünmesinde bir sakınca yok 😋)

Projenin varnishsiz halini :8080 portunda, varnishli halini :8000 portunda ayağa kaldırdım

Elimizde, sayfa yüklenirken iş yükü fazlaymış gibi görünen bir sayfa mevcut. Apache Benchmark ile sayfaya yük testi yapıyoruz. Servisimize 100 (-c 100) paralel kaynaktan 5000 (-n 5000) istek gönderiyorum.

$ ab -n 5000 -c 100 http://localhost/8080/

5.000 isteğin tamamlanması (Complete requests) 255,407 saniye (Time taken for tests) sürmüş. Bu da saniyede toplam 19,53 isteğe (Requests per second) cevap verebilmişiz demek.

Bir de Varnish ile deneyelim:

$ ab -n 5000 -c 100 http://localhost/8000/

Bu sefer, 5.000 istek (Complete requests), 1,918 saniyede (Time taken for tests) döndü! Ve saniyede 2.606,63 isteğe (Requests per second) cevap verebilen bir sunucumuz oldu.

Varnish bulunmayan ortamda saniyede 19,53 isteğe karşılık verebilirken Varnish kullanılan sunucuda saniyede 2.606,63 isteğe cevap verilebiliyor. Bu da 100 kattan daha fazla kazancımız var demek. Kabaca, 100 tane sunucunun işini tek sunucuda yapabildik anlamına geliyor.

Bu uygulamaya ait kodlara varnish-caching repomdan erişebilirsiniz.

Varnish CachingCachingVCLMemcacheHigh-performanceApache Benchmark