Yüksek Stres Altındaki Web Uygulamalarında Performans Yönetimi

Kabul etmeliyim ki bu başlık için kitap yazılır.

Günümüz dünyasında internetin ve doğal olarak web uygulamalarının, hayatımızın her noktasına en kritik yerden dokunduğunu sanıyorum söylemeye gerek yok. Notlarımızı tuttuğumuz Evernote’tan basit iş süreçlerini yönettiğimiz Trello’ya, müziğe ihtiyaç duyduğumuz her an ilk durak noktamız Spotify’dan, takip ettiğimiz dizinin ilk bölümünü dahi kesintisiz sunan Netflix’e kadar her bir uygulama günlük rutinimizin birer parçası. Tam bu noktada ise yazılımcılara düşen en önemli görev, tüm bu “yüksek stres altındaki web uygulamalarını” her an hizmet verebilir, rutini yavaşlatmayan, tabiri caizse bir performans canavarı haline getirebilmek ve bunu bir sürece yayabilmek.

Gerçek bir performans canavarı :)

Bu tür uygulamaları bahsi geçen yük ve stres altında ayakta tutabilen ve hizmetine kesintisiz — stabil — devam etmesini sağlayan onlarca araç ve yazılım, BT dünyasında mevcut. Hemen ilk akla gelenleri sıralamak gerekirse, Ngnix, Redis, Netscaler, Elasticsearch, Varnish, Elastic Load Balancing, aiScaler, Cassandra gibi ürünler; bu tür uygulamaların mimarilerinde önemli yer edinmiş durumdalar. İlerleyen teknolojiye ve web dünyasının büyüyen ihtiyaçlarına bakıldığında ise bunlara benzer ve çok daha performanslı ürünlerin geleceğini söylemek, falcılık olmayacaktır.

Bu başlık altında — ki “tutorial” vari bir mini yazı dizisi planlamaktayım — bu ürünlerden birini incelemeye ve teknoloji dağarcığımıza eklemeye çalışacağım. Bu ürün ise bir üst paragrafta kalın harflerle yazılı olan Varnish.

Varnish — Logo

Varnish literatürde kendisini şöyle tanımlıyor: “İçerik ağırlık dinamik web uygulamalarındaki request (istek) — response (cevap) döngüsünü hızlandırıcı bir önbellekleme uygulaması”. Yani diyor ki, back-end’e gelen isteklerin önüne kendimi konumlandırır, gelen isteği çok hızlı bir şekilde filtreleyip yorumlayabilir ve buna karşılık olarak üzerimde tuttuğu en yeni kopyayı cevap olarak dönebilirim. Birazdan ve sonraki yazılarımda da bahsedeceğim üzere bir konfigürasyon dosyası üzerinden çalışan bu uygulama, isteğe ait bir takım özellikleri (request headers, state objects) by-pass edebiliyor, daha öncesinde back-end sunucundan almış olduğu önyüz kopyasını yine sizin istediğiniz cevap özelliklerini (response headers) ekleyerek son kullanıcıya geri iletebiliyor. Böylece gelen istekler arka bahçeye geçmiyor ve asıl işi yapan (veritabanından veriyi alıp, işleyen; bir takım mantıksal süreçlerden geçirip önyüzü çizen ya da bir end-point olarak davranıp formal olarak veriyi dönen) uygulamanız mevcut performansını stabil bir şekilde sürdürebiliyor.

Açık kaynak kodlu olarak geliştirilen Varnish, ek modüllerle işlevselliğini arttırabilir bir özelliğe de sahip. Sadece önbellekleme değil; load-balancing (round-robin ve random), GZip compression/decompression, rule-based redirection gibi temel özellikleri de üzerinden barındırıyor.

Yukarıda bahsettiğim konfigürasyon dosyasının Varnish tarafındaki uzantısı, vcl. Nam-ı diğer “Varnish Configuration Language”. Adından da anlaşılacağı üzere Varnish sunucusuna gelen isteklerin nasıl karşılanacağı ve nasıl işleneceği bu ayar dosyasında tanımlı. İlgili dosya aslında C tabanlı bir program ve oldukça da performanslı. Devam eden yazılarda dosyanın ayrıntılarına girmeye çalışacağız ancak en basit haliyle şudur demek mümkün:

Programın bize söylediği ise şu: “Bu program 4.0 versiyon ile derlenecektir. Dolayısıyla daha önceki versiyonlarda yazılmış olan VCL komutları geçersiz olabilir. Varsayılan olarak bir back-end sunucu tanımlıyorum. Bana gelen isteklere önbellekten yanıt veremediğim takdirde 127.0.01:8080 adresli back-end uygulamasına gideceğim ve gelen cevabı işleyip son kullanıcıya ileteceğim.”

Kısa ama öz bir takım teorik bilgilerden sonra gelelim başlangıç için örneğimize. Varnish, Windows işletim sistemleri üzerinde çalışabilir bir uygulama değil. Dolayısıyla örneklerimde Ubuntu işletim sistemini kullanacağım. Bunun için de Docker’ı kullanmayı uygun gördüm. Eğer bilgisayarınızda kurulu değilse bu adresten indirebilir ve kolayca kurulumunu gerçekleştirebilirsiniz.

Back-end uygulaması olarak bir Tornado uygulaması geliştirelim. Geliştireceğimiz uygulamayı sunacak Docker container’ı için aşağıdaki docker komutlarını çalıştırmak yeterli olacaktır:

İlk satırdaki komutta, “Docker Store” içerisinde yer alan python container’ının indirilmesi sağlanıyor. Daha sonra ise her bir argument aşağıda açıklandığı şekliyle container aktif hale getiriliyor.

Eğer herhangi bir hata almadıysanız aşağıdaki ekranla karşılaşmanız doğru yolda olduğumuzu gösteriyor:

İçerisinde Python 3.6.1 kurulu bir container

Container şu anda fazlasıyla boş. Öncelikle “apt-get update” komutu ile Linux paketlerini güncelleyelim. Sonrasında ise örnek olarak seçtiğimiz Tornado uygulamasının çalışabilmesi için gerekli olan python paketini “pip install tornado” komutu ile indirelim. Bir sonraki adımda C:/python-scripts klasörünün altına aşağıdaki kodları içeren bir main.py dosyası oluşturalım ve hemen ardından “python /etc/scripts/main.py” komutunu çalıştıralım.

Şimdi tarayıcımızı açalım ve adres satırına localhost:1905 yazalım, eğer aşağıdaki ekranı görüyorsak, back-end uygulamamız hazır demektir:

O halde yeni bir Powershell ekranı açalım ve aşağıdaki komutları çalıştıralım. Aşağıdaki komutlara göre yeni bir — son versiyon — Ubuntu container’ı indireceğiz ve bu container’ı yine aşağıda açıklandığı şekilde çalışır vaziyete getireceğiz.

“docker run” komutunun argümanlarının açıklamaları ise aşağıdaki gibi:

Bu container’da tabii ki diğeri gibi boş. Bir öncekinde yaptığımız gibi “apt-get update && apt-get install curl && apt-get install varnish” komutlarını çalıştırıyoruz. Böylece sırasıyla Linux paketleri güncelleniyor, “curl” ve “varnish” adlı iki paket de container’ımıza dahil ediliyor. Curl paketini, eşleştirdiğimiz ve “tornado-app” hostname’i ile tanımladığımız ilk container’a erişip erişemediğimizi kontrol etmek için kullanacağız. Tüm paket kurulumları tamamlandıktan sonra “curl -l tornado-app:1905” isteğinden aşağıdaki sonuç dönüyor ise finale çok az kaldı diyebiliriz.

Şimdi “ls /etc/varnish/ -1a” komutunu çalıştıralım ve aşağıdaki çıktıyı alabildiğimizden emin olalım. Ayrıca aşağıdaki ekran görüntüsünde yer alan tüm dosyalar C:/Varnish/ klasörünüzde de yer almalıdır.

Eğer her şey — hala — istediğimiz gibi gidiyorsa C:/Varnish/default.vcl dosyasını bir metin editörü yardımıyla açalım ve aşağıdaki vcl tanımlamasını yapalım. Böylece Varnish sunucusuna gelen istekler back-end sunucusu olarak tornado-app:1905 adresini kullanacak ve buradan gelen cevabı önbellekleyip istemcilere iletecek.

Son adım olarak “service varnish start” komutu ile varnish servisimizi başlatalım ve localhost:6081 adresine gidelim. İlk istekte aşağıdaki gibi header bilgileri görünecek:

“X-Cache” header’ı, bu sayfanın (Varnish için bir obje) bir önbelleği olmadığını söylüyor (MISS). Sayfayı yenilediğimizde ise bu değerin “HIT” olarak geldiğini göreceğiz. Bunun anlamı ise, bu kopya için back-end sunucusuna gitmeye gerek duymadım çünkü bir kopyası bende zaten vardı! Ben de sana bunu teslim ediyorum.

Bununla beraber Varnish’in eklediği bir takım header bilgileri de mevcut (age, x-varnish gibi). Bunları ve yukarıdaki vcl dosyasında tanımlı fonksiyonları bir sonraki yazıda — girizgahı çok uzun tutmadan — açıklamaya ve örneklerle göstermeye çalışacağım.

O zamana dek, uygulamalarınız hep ayakta, cache objeleriniz hem validate olsun.