Proxy Cache nedir ve nasıl kullanılır?

Bu flood’da Nginx'in Proxy Cache özelliği üzerinden bir önceki flood'da bahsedilen CDN'in nasıl çalıştığını anlatacağım.

CDN'in orijin sunucu ile istemci arasına girerek bütün istemciler için aynı olan (CSS, JS, imaj) gibi kaynakları cache'leyerek istemcilere ilettiğini söylemiştik. CDN burada ilk istek için bir Proxy sunucu, sonraki istekler için ise cache sunucu gibi davranmaktadır.

Bütün trafiğin CDN üzerinden geçtiği senaryoda (CloudFlare, Fastly) ise CDN, cache'lenemeyecek (API, vb) kaynaklar için Reverse Proxy görevi üstlenerek istemciden gelen isteği direkt olarak orijin sunucuya geçirip gelen cevabı ise tekrar istemciye iletir.

Önceki yazıların birinde Reverse Proxy ve Forward Proxy kavramlarının ne anlama geldiğini incelemiştik. Bu yazı https://medium.com/@gokhansengun/27f2a1fc634c linkinden incelenebilir.

CloudFlare ve Fastly'nin verdiği Reverse Proxy ve Proxy Cache hizmeti özel ihtiyaçlar için açık kaynak kodlu Nginx ve Varnish yazılımları ile de yerine getirilebilir. Burada özel ihtiyaç'tan kasıt aslında klasik anlamda bir CDN ihtiyacı dışındaki ihtiyaçlardır. Örneğin, şirket içi ağda kullanıcıların yoğun olarak indirdikleri dosyalar yine şirket ağında bulunan bir sunucuya kurulacak Proxy Cache yardımıyla cache'lenebilir. Bu sayede hem internetten indirilen bayt miktarı azaltılır hem de kullanıcılar zaman tasarrufu sağlar.

Bu yazıda sadece Proxy Cache özelliğini inceleyeceğimiz Nginx, C10k Problem olarak bilinen ve onbin bağlantıyı aynı anda karşılama problemini çözmek üzere yola çıkmış bir web sunucu, yük dağıtıcı ve vekil sunucudur (Proxy Server).

Nginx ile Proxy Cache konfigürasyonunun ilk adımı aşağıdaki gibi cache'lenecek kaynakların tutulacağı süre, disk bölgesi, vb detayların belirlenmesidir.

Konfigürasyonda belirtilen keys_zone=cache:10m ile cache adlı bir zone yaratılarak bu alanda tutulacak kaynakların metadatası için 10 MB yer ayrıldığı ifade edilmiştir. max_size=50g direktifi ile ise tutulacak toplam dosya boyutu 50 GB ile sınırlanmıştır. Bu sayede disk üzerindeki bütün boş alanın cache olarak kullanılması engellenmiştir. Toplam cache boyutu 50 GB'ın üzerine çıktığında erişim zamanı bakımından en eski olan kaynaklar silinir. inactive=60d direktifi ile ise 60 gün boyunca erişilmeyen kaynakların silinmesi belirtilmiştir.

Cachelenen kaynakların dosya ismi içeriğin hash’i olacak şekilde saklanır. Hash’i hesaplanan dosyaları bulma işlemini hızlandırmak için konfigürasyonda verilen levels=1:2 yönergesi uyarınca dosyalar aşağıdaki gibi klasörlere bölünmüş ve bir nevi tree yapısı oluşturulmuştur.

Nginx'in kaynakları hangi parametrelere göre cache'leyeceği proxy_cache_key'e göre belirlenir. Aynı proxy_cache_key'e sahip isteklere ilgili key için cache'lenmiş cevap dönülür. Farklı isteklere aynı cevabı dönmemek için bu key granüler olarak belirlenmelidir.

Nginx'in sunduğu ileri seviye özelliklerinden biri proxy_cache_lock'dur. Bu özellik ile Nginx aynı proxy_cache_key'e sahip olan isteklerin sadece birini orijin sunucuya geçirerek diğer istekleri belirli bir süre bekletir, gelen cevap bütün istemcilere iletilir.

proxy_cache_lock özellikle cache temizlenme aralıklarında yapılan isteklerde upstream veya origin sunucuya fazla yük bindirmemek için çok önemlidir.

Nginx, ön tanımlı olarak sunucudan gelen cevap başlığındaki Cache-Control değeri Private, No-Cache veya No-Store bulunan paketler ile Set-Cookie bulunan paketleri cache'lemez çünkü sunucu bu başlıklarla cevapların kullanıcıya özel olduğunu açıkça belirtmektedir.

Bazı özel durumlarda (sunucunun cache’lenebilecek cevaplarda da ilgili başlıkları kullanması, vb) Nginx'in yukarıda verilen default davranışı proxy_ignore_headers Cache-Control; direktifi ile ezilebilir.

Dikkat edilmesi gereken bir diğer husus Nginx'in hatalı yapılandırıldığında orijin sunucudan gelen 4xx ve 5xx'li hata cevaplarını da cache'lemesidir. Özel durumlar hariç Nginx sadece 2xx ve bazen 3xx'li cevapları cache'lemesi için yapılandırılmalıdır.

Yine dikkat edilmesi gereken önemli bir nokta Nginx'in 3xx'li redirect cevaplarını ön tanımlı olarak takip etmeyerek direkt olarak sunucudan dönen değeri cache'lemesidir. Burada bu istekler proxy tarafından takip edilip asıl cevap cache'lenmeli ve istemciye sunulmalıdır.

Proxy Cache kullanılırken Proxy'nin istemciye döndüğü cevap başlığında isteği cevaplarken cache kullanılıp kullanılmadığını belirtmek için HIT, MISS, vb yazmak hem cache kullanımını görmek hem de problemleri debug etmek için iyi bir pratiktir.

Son olarak Nginx'in Proxy Cache özelliği geliştirme ortamlarının evcilleştirilmesi için sıklıkla tercih edilmektedir. En yaygın iki örnek şirket içindeki bir sunucuda Proxy Cache ile NPM repolarını ve Docker imajlarını cache'lemek olarak verilebilir.