CodeIgniter için Nginx + PHP5-fpm kütükleri

Ubuntu altında nginx server ve php5-fpm kurarak CodeIgniter çalıştırmak için gerekli bir takım ayarlar.

meso burada kullanıcı adıdır.

server {
 listen localhost:80;
 root /home/meso/Public/keypad/root;
 index index.php index.html index.htm;
 server_name localhost;
 include /etc/nginx/ci_host;
 }

ci_host dosyasının içeriği aşağıdaki gibi olmalıdır.

# /etc/nginx/ci_host
 index index.html index.php index.htm;
location / {
 try_files $uri $uri/ /index.php;
 }
location ~* \.php$ {
 fastcgi_pass unix:/var/run/php5-fpm.sock;
 fastcgi_index index.php;
 fastcgi_split_path_info ^(.+\.php)(.*)$;
 include fastcgi_params;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 }

İlişkisel Veritabanları

Bir tablo bir tek varlığa ait bilgileri tutmak için tasarlanır. Örneğin bir kitap tablosundasadece kitaplara ait bilgiler vardır. 20 adet kitap bilgisi varsa, bu tabloya 20 adet satıreklenecek demektir. İlişkisel veri tabanı yaklaşımını ilişkisel yapan asıl unsur verilerintablolara parçalanarak saklanmasıdır.Tabloların kaç adet olacağı ve birbiriyle nasıl ilişkilendirileceğine karar verirken varolan kuralları kullanarak mantıksal bir plan ile hareket edilir.Eğer tablolar üzerinde verileri normalize etmezseniz birçok sıkıntı oluşabilir. Bazıbilgiler birden fazla tekrarlanabilir. Bir bilgiyi güncellemek, veri eklemek ve silmek içinbirden fazla yerde bulma, değiştirme ve silme yapmanız gerekebilir. Bu nedenlenormalizasyon kurallarını kullanmalısınız.Genel kabul gören beş normalizasyon kuralı vardır. Bu kurallar, ilişkisel veri tabanınıntanımı ile birlikte ortaya konmuştur. Veri tabanı normalizasyonu Resim 2.1′e bağlı olarakanlatılacaktır. Açıklamalar yapılırken bu resme dikkat etmelisiniz.

diagram_1

1. Normalizasyon Kuralı
Bir satırdaki bir alan yalnızca bir tek bilgi içerebilir.Örneğin kitap tablosunda, birden fazla yazarı olan kitap için yazar1, yazar2, yazar3diye alanlar açsanız, bu kurala uymamış olursunuz. Böyle bir durumda, ayrıca yazarlartablosu da oluşturarak kuralı çiğnememeye dikkat etmelisiniz.

2. Normalizasyon Kuralı
Bir tablo için, anahtar olmayan her alan, birincil anahtar olarak tanımlı tüm alanlarabağlı olmak zorundadır.Mesela, Ödünç tablosuna KitapAdi diye bir alan ekleseydik, bu sadece ödünç verilenkitap ile ilgili bir bilgi olacaktı ve oduncNo’na bağlı bir nitelik olmayacaktı. Bunu çözmekiçin, kitap adlarını ayrı bir tabloda tutarak sorun çözülür.Ya da anahtar alanın birden fazla alandan oluştuğu tablolarda, anahtar alanlardansadece birine bağlı veriler, tabloda yer almamalı, ayrı bir tabloya taşınmalıdır.Bunun tersi de geçerlidir. Yani iki ya da daha fazla tablonun birincil anahtarı aynıolamaz. Şayet böyle ise, bu iki tablo tek tabloya indirilmelidir.

3. Normalizasyon Kuralı
Bir tablo için, anahtarı olmayan bir alan, anahtarı olmayan başka hiç bir alana bağlıolamaz. Örneğin, kitaplarımız için cilt tipi adında bir alan ekleyip burada da karton kapak içinK, deri cilt için D, spiral cilt için S yazsaydık, bu kodlama, kitap tablosunun birincil anahtarıolan kitapNo alanına bağlı bir kodlama olmayacaktı. Çünkü bu kodlama bir başka anahtarıolmayan alana bağlıdır. Bunun sonucunda da veri tabanımızda, karşılığı olmayan birkodlama yer almış olacaktır. Cilt tipi bilgisini kodlu olarak tutan alan aslında cilt tipiaçıklaması olan başka bir alana bağlıdır. Bu ilişki başka bir tabloda tutulmalıdır.Bu durumda, ciltŞekli adında bir tablo açmamız gerekir. Bu tablonun alanları daciltTipKodu ve ciltSekli olmalıdır. Ancak bundan sonra, kitaplar tablosunda ciltTipi adındabir sütun açıp buraya da D,S,K gibi kodları yazabilirsiniz.

4. Normalizasyon Kuralı
Birincil anahtar alanlar ile anahtarı olmayan alanlar arasında, birden fazla bağımsızbire-çok ilişkisine izin verilmez.Örneğin, tablomuzda yer alan bir kitap hem hikaye kitabı hem de kişisel gelişim kitabıolabilir.4.normalizasyon kuralını sağlamak için, her bağımsız bire-çok ilişki için ayrı bir tablooluşturmak gerekir.Bu örnekte, türler diye bir tablo açmamız ve daha sonra da kitapTurleri diye bir başkatablo daha açmamız gerekiyor. “Kişisel Gelişim Hikâyeleri” adlı kitap için, öncelikle kitapnumarası, Hikâye bölümünün kodunun yer aldığı bir satır; ardından da yine kitap numarası,ardından da kişisel gelişim türünün kodunun aldığı yeni bir satır daha eklemek gerekir.

5. Normalizasyon Kuralı
Tekrarlamaları ortadan kaldırmak için her bir tabloyu mümkün olduğunca küçükparçalara bölmek gerekir. Aslında ilk 4 kural sonuçta bu işe yarar ancak, bu kurallarkapsamında olmayan tekrarlamalar da 5.normalizasyon kuralı ile giderilir.Örneğin, kitaplarımız için bir edinme şekli bilgisi girilecek sütun eklemek isteyelim:Bu bölüme girilebilecek bilgiler bellidir: Bağış veya satın alma gibi.Bu bilgileri başka bir tabloda tutabiliriz. Böylece, kullanıcıların bu alana gelişigüzelbilgiler girmesini engellemiş olursunuz. Bu da sorgulama esnasında verileriniz arasında birtutarlılık sağlar. Bu işlem sonucunda, tutarsızlıklara neden olabilecek ve sık tekrarlayan “look-up table” terimi kullanılır.Ancak, veri tabanı normalizasyon kuralları, bir ilişkisel veri tabanının tasarlanmaaşamalarını değil de ilişkisel veri tabanında yer alacak kayıtların ilişkisel veri tabanı ileuyumlu olup olmadığını denetlemeye yöneliktir.Özetle ilişkisel bir veri tabanı tasarımı şu dört ögeyi barındırmalıdır.* Veri tekrarı yapılmamalıdır.* Boş yer mümkün olduğunca az olmalıdır.* Veri bütünlüğü sağlanmalıdır.* Veriler, aralarında bir ilişki tanımlamaya müsait olmalıdır.

KAYITLARIN İLİŞKİLENDİRİLMESİ
İlişkiler tablolardan verileri birbirine bağlayarak tabloların kullanışlılığını artırır.Böylece ilişkisel veri tabanları oluşturulur. Veriler konu veya göreve göre çeşitli tablolardadepolanır, ancak veriler ilişkilidir ve belirttiğiniz şekilde bir araya getirilebilir.Tablolar arasında ilişki kurmak suretiyle, veri tabanı dosyası düz veri tabanı olmaktankurtarılır. Tablolar arası ilişki, daha hızlı sorgu icrası yapılmasını sağlar; veri-işlem işleridaha verimli olur. Bu sayede verileri güncelleştirirken, bütün tabloları elden geçirmek vehatta yeniden girmek zorunda kalınmaz. Sadece güncelleştirilmesi gereken tabloya ek veyabu tabloda değişiklik yapılır.İlişkilendirme temelde bir tablodaki varlığa ait bilgilerin anahtar olan sütundanhareketle başka bir tablodan takip edilmesini sağlar. Tablolar arasında üç tip ilişki vardır.

1.Bire-Bir İlişki
İlişkilendirdiğiniz iki tablodan birincisi ile ikincisi arasında sadece bir kayıteşleşebilir. Bu tür ilişkilere bire-bir ilişki denir. İki tablo arasında bire bir ilişki varsa bu ikitablo birbirinin devamı demektir ve genellikle bir tek tablo olarak birleştirilir. Bu türilişkilendirme tablolarda sık kullanılmaz.

2.Bir-Çok İlişki
En çok kullanılan ilişki şeklidir. Bu ilişkide A tablosundaki bir kayıt B tablosundakibirden çok eşleşen kayda sahiptir. Bunun tersi doğru değildir. Yani B tablosundaki bir kayıtA tablosundaki yalnızca bir kayıt ile eşleşir.Örneğin, Müşteriler ve Siparişler tablolarının birçok ilişkisi vardır: Her müşteribirçok sipariş verir ancak her sipariş bir müşteriye aittir.

3. Çok-Çok İlişki
Bir çok-çok ilişkide, A tablosundaki bir satırın B tablosunda çok sayıda eşi vardır vetam tersi de geçerlidir. Bu tür ilişkileri, birincil anahtarları A ve B tablolarının yabancıanahtarlarından oluşan bağlantı tablosu diye adlandırılan üçüncü bir tablo tanımlayarakoluşturabilirsiniz.

Bu yazı http://bildirgec.org/yazi/relational-database-iliskisel-veritabani-yapisi/ adresinden alınmıştır.

Webde yüksek verim ve Cache

Webde yüksek verim nedir ve genel olarak kullanılan cache(ön bellek) sistemleri nelerdir biraz bakalım. Cache dediğimiz konu aslında temel olarak webdeki program, web server veya database’in üstüne düşen yükün azaltılarak kullanıcıya daha hızlı şekilde verilmesi esasına dayanır.Yazıyı normalde üç veya dört parçaya bölmeyi düşünmeme rağmen konunun bütünlüğünün bozulmaması için çok fazla bölmemek gerektiğini düşünüyorum. Basitten gelişmiş anlatıma doğru giderek, sadece memcache konusunun detayı fazla olduğu için memcache konusunu farklı bir başlık altında anlattım. Bu yazıda ise biraz daha özet olarak memcache’den bahsedeceğim. Yazıda her dile uygun olabilmesi için, code örnekleri yerine genel olarak yapıyı sorunları ve cözümleri anlatmaya çalıştım. Genede PHP ağırlıklı bir yazı olduğunuda kabul etmek gerekiyor.Cache sistemleri kullanırken genel olarak altın kural diyebileceğim dört tane durumu akıldan çıkarmamak gerekiyor.• Cache sistemleri asla bir veritabanı değildir, cache’e eklediğiniz bir verinin illaki orada olmasını bekleyemezsiniz. Dolayısıyla programınızı cache’deki verinin asla kaybolmayacağını düşünerek yazmamak gerekmektedir.

Program yazarken cache konusunu her zaman düşünmek ama cache yokken çalışabilmesini sağlamalıyız. Program yazımına başladığınızda en baştan yüksek verimliliği göz önünde bulundurarak, cache olacağını akılda tutarak yazmak ama programın cache olmadan çalışabileceği esasına dayanmak gerekmektedir.

Cache’lerde invalidate etmeyi eğer siteniz büyümeye yatkınsa tek server üstünden düşünmemek gerekir. Eğer web sitenizin kullanıcısının artacağını düşünüyorsanız, birden çok web ve/veya database server’ın işin içine gireceğini en baştan düşünmelisiniz.

Veri tabanını programınızda kullanımınız eğer okumaktan çok daha fazla yazmak üzerineyse dinamik cache kullanmanız çok mantıklı değildir.

Cache sistemlerini sanırım statik ve dinamik olarak iki grup altında toplayabiliriz.

Statik Dosyaların Cache’lenmesi:
Statik dosya cache inin içine neler giriyor diye düşünürsek, değişmeyen html dosyalarınız javascript dosyaları, imajlhttp://bildirgec.org/yazi/cache-proxy-web-ustunde-yuksek/ar, videolar, css dosyaları.. gibi gidebiliriz. Statik cache her zaman dinamik cachelenmeye göre daha hızlıdır. Bu yapının içine daha çok web browserlar, proxyler ve web serverlar girmektedir.

Dinamik Verilerin Cache’lenmesi:
Benim tüm sayfam dinamik hiçbir şeyi cache’leyemem. Evet bu oldukça çok duyduğumuz bir söz ama maalesef doğru değildir. Sayfanızın belirli elemanları her zaman aynı kalmaktadır. Veri tabanından genel olarak çektiğiniz ve gösterdiğiniz veriler aynı olacaktır. Aradaki 5 saniye bile cache yapsanız web sitenize giren kişi sayısı saniyede 100 kullanıcı bile üzerindeyse çok ciddi avantaj sağlayacaktır. (Bu rakam büyük sitelerde 1000, 2000 gibi sayılara çok rahat ulaşabilmektedir) Bu konu altına cookie, memcache, file, apc (veya benzeri shared memory uygulamaları, çözümleri) gibi cache çözümleri girmektedir.

Statik Dosya Cache:
Browser Cache:
Öncelikle browser cache den bahsedelim. Web serverınıza düşen yükü azaltmanın yegane yolu budur aslında, yeni nesil browserlar siz client(istemci) tarafında aksini yapmasını söylemediğiniz sürece web server’ın verdiği şartlara uygun olarak dosyalarınızı cache’lerler. Bu cache sistemi RFC 2616 ya göre gönderdiğiniz header bilgilerine göre işlemektedir. Bu işi genel olarak apache, lighttpd, nginx gibi web serverlar doğru şekilde ayarlarsanız sizin üzerinizden alarak otomatik yapabilmektedir. Apache web server’da mod_expires, lighttpd web server’da mod_expire , nginx web server’da da expires komutu ile yapılabilmektedir.Browser cache in genel problemi ise, gelişen web sitelerinde static dosyaların dahil her zaman değişime maruz kalması zorunluluğudur. Karşımıza şöyle bir problem çıkmaktadır. Örneğin kullanıcı avatarını değiştirdiğini varsayarsak, eski resim artık geçersiz olsa bile kullanıcılarınız cache süresi dolana kadar eski resmi görecektir.Bu sorunu çözmek için ise statik dosyalara isim verirken timestamp eklemek yada belirli bir id yi her defasında artırarak dosya ismine eklemekten geçmektedir. Örneğin eğer kullanıcı ikinci sefer avatar değiştiriyor ise nick-id.jpg seklinde kaydederken eğer ikinci avatar değişimi ise “darkelf-2.jpg” gibi kaydetmek sorunu cözecektir. Aynı durum sitenizdeki javascript dosyaları içinde geçerlidir. Eğer dosyayı upload ettiğiniz tarih + o gune ait bir idyi dosya ismine eklerseniz bu sorunu cözebilirsiniz örneğin “hede-2008112201.js” şeklinde isimlendirebilirsiniz.Programı yazan kişinin en baştan bu duruma uygun şekilde programı yazması gerekmektedir. Yoksa çok ciddi bir emek kaybı ile programın değişimi söz konusu olması gerekebiliyor.

Proxy Serverlar:
Her programın olduğu gibi web server’larında kendisine özgü limitleri olduğu tartışılmaz bir konu. Dolayısıyla static dosyalar için web serverların üstündeki yükü düşürebilmek için reverse proxy server mantığını kullanmanız gerekmektedir.Reverse proxy ler nasıl çalışır kısaca değinmek gerekirse kendisi üzerine bir istek geldiğinde ilk önce kendi cache’inde varmı diye bakar, varsa kendisi üzerinden hiç web servera sormadan verir, eğer yok ise web serverdan çekmeye başlar ve bu sırada kullanıcıyada gönderir ve ardından bu dosyayı tekrar istendiğinde vermek üzere kendi üstünde saklar.Reverse Proxy Server’ların bir dosyayı invalidate etmesi genel olarak ekstradan üstün gelen (override) bir ayar yapmadıysanız browser cache için gönderdiğiniz ayarları kullanır. Proxy serverlardan genel olarak benim gördüğüm en verimli çalışan iki tanesi Squid ve Varnish oldu. İkisinin de kendisine özgü avantajları bana göre farklı şekildedir.Squid proxy yapısında birden çok proxy serverın ortak çalışmasını sağlayabiliyorsunuz. ( – bende varmı? Yok. – Sende varmı varsa gönder ? Yok. – Sen bana şundan alıp versene gibi bir mantık dizisi içerebiliyor). Ayar yapması gerçekten zordur. Squid sistemi çok eski yıllardan beri var olduğu için işletim sisteminde sorun olan konuları kapatmaya göre çalışmaktadır. Memory allocation yapısını kendisi oluşturur. IO Systemi yönetir yani işletim sisteminin arkada yaptığı tüm işleri tekrar yapar ve buda sisteme ciddi bir overload yapmaktadır.

Varnish Proxy ise daha yeni bir proxy yapısı olduğu için farklı bir yapı kullanmış. İşletim sistemleri artık üstlerindeki işi en doğrusu ile yaptığını düşünerek(Evet o kadar kernel developer boş durmamaktadır) sistem ile dövüşmeden user space de programın kendisine düşen yükü mümkün olduğunca en aza indirerek bu işi yapmaktadır. Biraz teknik konuya girersek, Shared Memory doğru kullanımı tek bir bufferın tüm connectionlara hizmet verebilmesi gibi örnekler sayılabilir. Artı bir avantajı kendi içinde libgcc ile C dilinde script tarzı yazmanızı ve kendisinin bunu .so dosyasına çevirip yükleyebilmesini sağlamaktadır. Buda proxy i istediğiniz tarzda yönlendirebilmenizi yönetebilmenize izin veriyor, henüz bildiğim kadarıyla multi server’ın ortak çalışma özelliği yok.

Yaptığım testlerde bu iki yapının da küçük dosyalarda oldukça verimli iken dosyalar büyüdükçe (1M ve üzeri) , istek çoğaldıkca yada partial download çoğaldıkca sorunlar çıkardığını gördüm. Bu durum sizekendi proxy server’ınızı yazmaya kadar itebilmektedir.

Web Serverlar:
Proxy serverlar ile uğraşmak istemediğinizde bir başka çözüm ise normal kullandığınız application serverların yanına static dosyalar için daha lite(hafif) web serverlar koymaktır. Bunlara örnek olarak thttpd, lighttpd verilebilir. Bu Web serverların işlevi sadece statik dosyaları vermek olduğundan hem application serverdaki yükünüz azalır hemde daha hızlı şekilde dosyaları kullanıcıya ulaştırabilirsiniz. Ancak invalidate etme konusu ayrı bir sorundur ve dosya sayısı çoğaldıkça başka sorunlara yol açabilir. Dosyaların geç değişmesi kopyalamanın çok uzun sürmesi gibi.Buraya kadar anlattığım konular statik dosyalar içindi. Ne yazıkki sadece bunları yapmak verimli bir web uygulamanız olacak demek değildir. Dinamik caching büyüyen sitelerde mecbur kalınan bir yapıdır.

Dinamik Cache:
Cookies:
Coğu süreçte güvenlik yada session amaçlı kullandığımız cookie ler aslında caching sistemlerinin vazgeçilmez bir parçasıdır size kullanıcı sayfa isteği gönderirken zaten sizin database’den o kullanıcıya özgü çekmek zorunda olduğunuz verileri göndermesini sağlayabilirsiniz.Örnek vermek gerekirse web uygulamanızda mesajlaşma yorum yazma gibi konuların olduğunu ama yorum yazılacak profil sahiplerinin kendisine yorum yazamayacak kişileri seçebildiğini düşünelim. Bu durumda daha liste sayfasını oluştururken bile kullanıcının yorum yazamayacağı sayfalardan linkleri kaldırmanız gerekebilmektedir. Bu durumda web uygulamanızın yapması gereken şey ise listelediği kişi başına gezen kişinin mesaj atıp atamayacağını database yada diğer cache sistemlerinden sorgulamak olmaktadır. Veri tabanını buna özgü doğru şekilde tasarlamış tek sorguda yazamayacağı profilleri alabiliyor olsanız bile her şart altında bu bir yük oluşturmaktadır. Sayfayı gezen kişiye henüz cookiesi boş iken bu bilgiyi göndermek için Veri tabanından yada cache sisteminizden aldığınızı düşünelim sayfayı gösterirken cookie’yi kullanıcının makinesine atarsak eğer bir dahaki benzer profilleri gezdiğinde zaten daha bize istek sırasında gönderemeyeceği kişileri gönderecektir. Buda bizi gereksiz bir sorgudan kurtarmış olur. Genede güvenlik için cookie lere bel bağlayamazsınız gelen cookie içinde olmayan profilleri veritabanından test etmeniz her şartta gerekmektedir. Başta kücük bir getiri olarak gözükse bile web sayfanızda saniyede 100 lerce farklı kullanıcının aynı saniyede bu sayfaları çağırdığını düşünürseniz getirisi inanılmaz derecede fazla olacaktır.Cookie ler limitsiz değildir. Domain başına atabileceğiniz cookie sayısı ve büyüklüğü rfc ye göre en az 50 cookie ve cookie başına 4096 byte iken, durum daha çok browser specific’dir. Bildiğimiz kadarıyla browser’ların domain başına tutabileceği cookie sayısı;* Patchlenmemiş Internet Explorer 6: 20 cookie , toplamda 4096 byte* Patched Internet Explorer 6: 29/08/07 tarihinde microsoft 20 cookie yi 50 cookie’ye çıkarmış ama toplam limiti 4096 bırakmıştır.* Internet Explorer 7: 50 cookie, 4096 byte toplamda* FireFox > 1.5: 50 cookie, 4096 byte cookie başına* Opera: 30 Cookie* Safari: 1000 ve üzeri, 4096 byte cookie başınaBu limitleri cookie yazmadan önce hesaplamanız gerekmektedir. Eğer Internet Explorer 6 da 4096 byte’ı geçerseniz yeni cookie eklenmesine izin vermemektedir. Bu Cookie size a session id gibi cookielerinde dahil olduğunu unutmamak gerekmektedir. User Agent’a bakılarak browser’a özgü cookie ataması yapmak buradaki en doğru çözümlerden birisidir. IE6 ve IE7 de kullanmamayı lütfen planlamayın, hala türkiyedeki büyük çoğunluk Internet Explorer 6 kullanmaktadır.Cookie leri kullanmamız gerekmektedir ancak dikkat edilmesi gereken bir konu bu cookielerin boyutunu büyültmenin götürüsü arasında sadece internet explorer 6 ve 7 deki sorunları değil aynı zamanda kullanıcı her sayfanızı çağırışında size cookie boyutu kadar bir veriyi göndermek zorunda bırakmanız belirli ölcüde request zamanını ve dolayısıyla sayfanızın kullanıcıya geliş hızını düşürecektir. Dolayısı ile doğru ve gerekli şekilde cookieleri kullanmak her zaman için avantajdır.

File Cache:
Sayfalarınızı dinamik oluşturduğunuz süreçleri genel olarak azaltmanın en çok kullanılan yollarından birisidir. Sayfada bir değişiklik olmadığı süreçte sayfa dinamik olarak hazırlandıktan sonra bir dosyaya kaydedilerek sonraki çağırımlarda, o sayfanın statik bir html dosyasından okunarak verilmesi esasına dayanır. Bir değişiklik yapıldığında ise o sayfa tekrar yartılarak yeni isteklere hazır hale getirilir. Eğer sayfamda her daim değişen bir şeyler var diyorsanız değişmeyen kısımlarını birkaç dosyaya bölmeniz o dosyaları oluşturmanız için gereken Veritabanı erişimlerini azaltacağı için ciddi avantaj sağlayacaktır yani web sayfasını olduğu gibi tek bir dosyada tutmanız her zaman olası değildir.Ne yazıkki file cache sorunsuz değildir, birkaç genel problemi vardır. Bunlardan ilki disk’e bağımlı olduğunuz için diğer cache sistemlerine göre daha yavaş çalışıyor olmasıdır. Diğer bir noktasıda filecache oluşturma sürecini atomic(Bir anda) yapmak zorunda olmamız, yani biz sayfayı oluştururken kullanıcı gelirse o sayfanın yarıda kalmış eksik halini görmemesi gerekir. Cözümü genel olarak başka bir dosya adı ile oluşturup adını olması gereken dosyaya çevirmektir. Directory başına oluşturduğunuz cache file sayısıda bu konuda sisteminizin yavaşlaması için etkendir. Belirli bir hashing algoritmasına göre alt directory’lere bölmeniz gerekmektedir. En önemli sorunu ise eğer birden çok web serverınız varsa iki ayrı sistemin invalidate etme durumlarında ortak çalışmaması olacaktır. Bu konuda maalesef samba nfs tarzı paylaşımlı directory kullanmak verimi dahada düşürüp network yapınız üzerine yük bindireceğinden kullanmamak gerekir. En doğru yöntemi ise biraz alt düzey yapı oluşturarak bir deamon aracılığı ile değişiklikleri kontrol edip invalidate olmuş cache dosyasını silmektir yada bu işi memcached gibi network üstünden çalışan sistemler ile invalidate kontrollu hale getirmektir.Tek başına file cache kullanımı disk ömrünüzden yiyeceğini unutmamak gerekir ve örnek vermek gerekirse 1 milyon farklı sayfanız varsa 1 milyon dan biraz daha fazla cache dosyanız olacak demektirki buda file system için ciddi bir sorundur.

Memcache:
Memcache danga.com tarafından live journal için üretilen ama yapısı itibari ile çok hızlı şekilde popüler olmuş bir cache yapısıdır. En büyük avantajı network üstünden çalışabilmesidir, Network üstünden tcp/ip ile çalıştığı için file cache e göre daha yavaştır ancak ortak cache havuzunu kullanabiliyor olmanız gibi avantajları ve SQL serverlara göre çok daha hızlı olması sebebi ile ciddi tercih sebebidir. İçerisinde her türlü veriyi saklayabilmenizi sağlar. Atomic inc ve dec gibi fonksiyonlarıda ciddi bir avantaj sağlamaktadır.Anahtar ve veri şeklinde çalışmaktadır. Hız sebebiyle iteration yapılamamaktadır. Örnek verirsek eğer bir kullanıcınızın sayfası çok fazla istek alıyor. O kullanıcıya özgü verilerin her sayfa çağrışında veritabanından birden çok veri tabanı sorgusu ile okunması yerine kullanıcının id’sini anahtar olarak düşünüyoruz ve veri tabanından ilk seferinde çektiğimiz gerekli bilgilerini bu anahtar aracılığı ile memcache e kaydediyoruz. Ardından bir sonraki sayfa çağrıldığında memcache de gerekli bilgiler olduğu için veri tabanına birden çok sorgu göndermeden tek seferde bu veriye ulaşabilmekteyiz ve tüm web serverların aynı ortak cachei paylaşıyor olmasından dolayı çok ciddi şekilde veri tabanına düşen yük azalacaktır.Dezavantaj olarak söyleyebileceğim noktası ise hız sağlamak için kullanılan slab allocation yapısının eğer düzgün kullanılmazsa sorunlar yaşatıp gereksiz memory kullanabileceği ve veriminin düşeceğidir.Memcache konusu biraz geniş olduğu için bundan sonraki yazıda daha çok detayına gireceğim.

Shared Memory:
Şimdi anlatacağım APC, Xcache, Eaccelerator gibi programlar ve Global variable kullanmak php development’a yöneliktir. Şirketimizin scability açısından genel olarak PHP’yi tercih ettiği için bu konularda genel olarak asp,ruby veya benzeri sistemler yerine PHP üzerinde araştırma ve geliştirme yapmaktayız.

Global Variables:
Evet bildiğimiz global variable’lar projeler büyüyüp üzerinde çalışan kişi çoğaldıkca ve library bazında sistemler yazılmaya başlandıkca çok ciddi önem kazanmaktadır ve cache sistemi olarak kullanılabilmektedir. Direk uygulama içinde olduğu için diğer sistemlere oranla en hızlı çalışan cache sistemidir.Nasıl kullanıldığına örnek olarak bir sayfada birden çok SQL kullanmanız gerekmektedir. Kullanıcının son yazdığı entry i birden çok functionda kullandığımızı düşünelim. Eğer birden çok developer programın farklı yerlerini yazıyor veya yazdıysa birbirlerinden habersiz olarak aynı değerleri aynı php sayfasında bile cache sistemlerinden yada veri tabanından çekme olasılıkları çok yüksektir. Bu durumu yok etmek için cache yapısında kullandığımız anahtar mantığını global variable olarak düşünelim cache den veya veritabanından ilk çektiğimizde $GLOBALS[‘userid:darkelf’] = diye atama yapıyoruz. Ardından başka bir fonksiyonumuz aynı değere ihtiyaç duyacak olduğunda cache sistemlerine ve veritabanına sormadan önce anahtarı bildiğimiz için $GLOBALS da varmı diye bakıyoruz. İlk başta oldukça gereksiz bir yöntem olarak gözüksede projeniz büyüyüp birden çok kişi üzerinde çalışmaya başladığında tekrar tekrar çekilme olasılığını yok ettiği için olmazsa olmaz bir yapıdır.

APC, Xcache ve Eaccelerator libraryleri ve shmop_* functionları:

Bu 3 opcode cacher ve shared memory managerı sanırım aynı başlık altında toplamak daha mantıklı olacak. 3 ününde yaptığı iş aynı olsada yapış şekilerinde ve hızlarında farklılıklar vardır ve projeniz için birisinden birisini tercih etmeniz gerekmektedir. 3 ününde kendine özgü avantajları ve dezavantajları vardır.Bu librarylerin asıl görevi opcode caching dir. Bu ne demek siz bir php sayfasını çağırdığınızda PHP bu sayfanın codelarını her defasında kendi çalıştırabileceği hale getirmek için kendi opcode yapısına göre derler yani hafızada scriptler basic,qbasic zamanlarında olduğu gibi satır satır okunarak çalıştırılmaz. Önce tüm script okunur ve parsing in hız götürmeyeceği şekilde genelde instruction set’lerin 2 byte tutacağı hale çevrilir ve hafızada bu şekilde çalıştırılır. Oldukça doğru bir yöntem olmasına rağmen buradaki asıl sorun her sayfa çağrıldığında bu scriptlerin tekrar tekrar derlenmesi aslında gereksiz bir yöntemdir. PHP dosyaları cünkü çalışırken zaten bir değişime girmemektedir. Bu 3 library bu durumda kendilerine özgü hem php nin ürettiği opcode’u optimize eder, hemde php sayfaları çağrıldığında tekrar tekrar scriptlerin derlenmesi yerine php’ye kendi hafızalarından derlenmiş halini vererek aradaki derleme sürecini yokeder. PHP ile kod yazıyorsanız opcode cacher kullanmamanız için hiçbir sebep yoktur ve kullanmıyorsanız bu sizin sorununuzdur.Bu library ler opcode caching harici ayırdıkları hafızayı php ye library olarakda sunmaktadır yani uygulamanızda bir classın içeriğini, değişkeni yada herhangi bir veriyi ortak şekilde kullanabilmektesiniz. shmop_* functionları ile bu işi ben zaten yapıyorum diyorsanızda maalesef tuttuğunuz veriler çoğaldıkca shmop_* daki kullandığınız memory üzerine index mantığı getirmeniz gerekmektedir. Ne kadar doğru şekilde kodlarsanız kodlayın bu library’lerin bu işi yaptığı kadar hızlı ve doğru yapamayacaksınızdır. (C , PHP farkı) Bu yüzden shmop_* functionlarını kendi adıma bu library’ler varken kullanmanızı tavsiye etmiyorum.Bu 3 library de memcache gibi anahtar ve veri yapısını kullanmaktadır, web üzerinden PHP çalıştırmanın bildiğiniz üzere apache kullanarak shared library şeklinde, FastCGI arabirimi ile ve CGI olarak üç yolu vardır. CGI kullanıyorsanız eğer shared memory kullanmanızın hiçbir mantığı yoktur. Çünkü her sayfa çağrıldığında yeni bir php process’i yaratılacaktır ve ortak hafıza kullanamayacaktır. FastCGI ve shared library de ise durum farklıdır ve opcode cacherları bu iki arabirim sebebiyle daha çok kullanıma özgü ayırabiliriz.Opcode cacher lardaki genel bir sorun opcode cache kullanıyorsanız önemlidir. Eğer sayfanızdaki ziyaretciye özgü require yapıyorsanız örneğin eğer admin ise su dosyayı include et tarzı, opcode cacherlar oluşan compiled code değiştiği için her sayfanın farklı kullanıcı yapısına göre yüklendiğinde tekrar derlemek zorunda kalacaktır. Bu da opcode caching i CPU hungry duruma getirecektir.APC(Alternative PHP Cache) yaptığımız testlerde memory allocationdaki farklı yöntemi ile en hızlı çalışan opcode cacher ve library’dir. PHP 6 da standart olarak gelmesini düşünülüyor. Genel olarak dezavantaj diyebileceğim noktalar ise top level parent process e ait shared memory kullanmadığı için FastCGI tarzı yapılarda FastCGI daki PHP lerin respawn ömrü sonlandığında hafızayı boşaltması ve her FastCGI dan spawn olan PHP için ayrı birer shared memory kullanmasıdır. Bu durum php lerin opcode cacheleri icinde geçerli olduğundan web server’ınızın yükünü artırdığı gibi memory kullanımınızda artacaktır. Bunun harici memory allocation yapısındaki garbage collector tarzı ara ara temizlik yapması gerektiğinden FastCGI olsun olmasın ara ara web serverın cpu’sunu tavan yaptıracaktır. Turkish UTF Encoding ile ilgili sorunları olduğunuda projelerimizde gördük. FastCGI kullanıldığında bu durumda birden çok cache oluştuğu için Invalidate etmedede sorun çıkacaktır.Eaccelerator apc kadar hızlı olmamasına rağmen stability açısından daha sağlıklı sonuçlar doğurduğunu söyleyebilirim. Genel olarak farkı ise opcode cacheleri aynı zamanda diskede yazdığı için web server tekrar başladığında yada PHP processi tekrar başlatıldığında tekrar derlemek yerine diskden hızlıca derlenmiş halini okuyarak cpu yükünüzü azaltmasıdır. Genede fastcgi processlerinde top levent parent process e bağlanmadığı için APC gibi FastCGI da açtığınız PHP process’i başına ayrı memory tüketecektir ve sonlanacaktır. Haliyle bir web serverda birden çok cache yapınız ve farklı değerleri olabilecektir.Xcache lighttpd developerlarının çıkardığı daha yeni gelişen bir opcode cacher ve shared memory library’dir. Genel Olarak APC yada Eaccelerator’a göre daha yavaş çalışsada FastCGI processlerinde top level parent process e shared memory’i bind ettiği için tüm php process’lerinin aynı shared memory’i ve opcode cache’i kullanmasını sağlamaktadır. Stabilty konusunda eski versiyon’unda baya sorunlar çıksada, bir projemizde yeni versiyon’unun uzun süredir sorun çıkarmadığını söyleyebilirim.Yaptığımız hız testlerinin sonucunuda paylaşayım, bu testler platform specificdir sonuçları sizlerin sistemde farklı çıkabilir, tavsiyem yeni versiyonları ile kendinizinde benzer testler yapmanız ve buna göre hangisini kullanacağınızı seçmenizdir.

APC:Saniyede 615563 okuma yapabildi.
Eaccelerator:Saniyede 320624 okuma yapabildi.
Xcache: Saniyede 290950 okuma yapabildi.

Sonuç:
Kendi yaptığımız hız testlerini paylaşıyorum, dediğim gibi sonuçlar platform specifictir ve kendinizinde benzer testler yaparak sırayı ve nasıl bir cache sistemi oluşturacağınızı seçmeniz en doğru yoldur. Herhangi bir şekilde programları karşılaştırmak amaçlı değildir burada vereceğim değerler sadece bizde çıkan test sonuçlarıdır.

Global Variables: 863856/sec
APC: 615563/sec
Eaccelerator: 320624/sec
Xcache:290950/sec
File: 48704/sec
Memcache: 35217/sec
Memcache(Multi Connection): 15230/sec

Peki hangi cache sistemi diye kendinize soruyorsanız, projenize özgü seçmeniz gerekmesine rağmen şahsi tavsiyem hepsini kullanmanızdır. Her cache sisteminin kendine özgü avantajları ve dezavantajları vardır. Doğru caching sistemi ise hepsinin ortak şekilde çalışarak en hızlı şekilde veriyi vermesi üzerine dayanır. En hızlıdan en yavaşa doğru bir yapı izleyerek cacheleri sorgulamak bu yüzden en doğru yol olarak gözükmektedir.Cache sistemlerinde dikkat edilmesi gereken en önemli noktalardan birisi uygulamanızın cache olmadığı takdirde doğru ve düzgün şekilde çalışabilmesidir. Cache sistemleri sistemin performansını server maliyetini düşürmeye yöneliktir ve her zaman olacaklar diye bir durum yoktur. Örnek vermek gerekirse google yada benzeri arama botlarının sitenizdeki daha önce kullanılmayan yada kullanıcılar tarafından çok az kullanılmış artık eskisi kadar kullanılmayan sayfaları hızlı şekilde çekmeye çalışacağıdır. Bu botların sitenizi tararken sisteminizin sorun çekmesi hem arama sonuçlarında çıkmanızı zorlaştıracak hemde sisteminizin geçici çökmelerle karşılaşmasına sebep olacaktır. Bu durum illaki arama botları değil kötü niyetli bir kullanıcı tarafındanda yapılabilecek bir konudur.Arama botları geldiğinde en önemli konulardan birisi Cache den olan varsa çekerken eğer yoksa geri global variable hariç cache’e yazmamaktır. Normal kullanıcınızın kullanmayacağı bir veriyi cache de tutup normal kullanıcınızın kullanacağı verileri cache den silmeniz sitenizi gene zor duruma düşürüp sistem sorunlarınızı artıracaktır. Bu yüzden user agent kontrol edilerek cache yapısına karar verilmesi gerekmektedir.Uygulamalarda yüksek verim sadece cache sistemlerine bağlı değildir. Kodun nasıl yazıldığından sistemin nasıl yapılandırıldığına, tasarıma kadar bir çok konuya bağlıdır. Fırsat bulursam başka yazılarda bu konulara da değinmeye çalışacağım.

Bu yazı şu adresten alınmıştır : http://bildirgec.org/yazi/cache-proxy-web-ustunde-yuksek/

Varnish Cache Kurulumu ve İstisnaları

Varnish bir cache sistemi. Yani sık ziyaret edilen siteler için önbellekleme oluşturup tekrar aynı sayfaların oluşturulmasına engel oluyor.

Ubuntu altında varnish kurulumu için;

apt-get install varnish

komutu yeterli. Varnish diğer servisler gibi;

service varnish restart

ile ayarlamalardan sonra yeniden başlatılabiliyor.

NginX için sites-available içindeki virtual hostlar içerisinde dinlenen portu varnish portu ile değiştirmeniz gerekiyor.
Tabi öncesinde Varnish ayarlarını yapmak gerekli.

/etc/varnish/default.vcl içeriğini şöyle değiştirebilirsiniz.

backend default {
.host = "127.0.0.1";
.port = "8080";
}

sub vcl_fetch {

# DEBUG - asagida sayfanin cache durumunu bir header'a debug icin yazalim

# Varnish cache'lenemeyecegini soyluyor
if (beresp.ttl <= 0s) { set beresp.http.X-Cacheable = "NO:Not Cacheable"; # cookie ekleniyor } elsif (beresp.http.set-cookie) { set beresp.http.X-Cacheable = "NO:Set-Cookie"; # cache'lenebilir icerik } else { set beresp.http.X-Cacheable = "YES"; } # diger ayarlar.. }

/etc/default/varnish dosyasında ise;

DAEMON_OPTS="-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,256m"

Buradan sonra nGinX için virtual hostlardaki Listen portunu 8080 yapmanız.

Varnish'in kurulduktan sonra çalışıp çalışmadığını anlamak için sayfanın http header bilgilerine bakmanız yeterli. Bu sayfalarda Varnish geçiyorsa sunucunuz cache üzerinden işlem yapıyor demek. Bu headerları;

curl -I http://localhost

şeklinde kontrol edebilirsiniz.

Varnish PHP için session başlatılmış sayfalarda cache yapmıyor. Aynı zamanda HTTP header içinde cache kapalı sayfalarda da cache yapmıyor.

Bu yazının oluşumunda Facebook PHP-tr grubunda Aykut Farsak'ın cevapları etkili olmuştur. Kendisine teşekkürler.