Sunucu Yükü ve Bant Genişliği Optimizasyonu
Bant genişliği için para ödüyoruz ki çoğundan kurtulabilir
para ve hız kazanabiliriz.
Aynısı sunucu için de geçerli.
İşlemci yükünü çok kolay bir biçimde rahatlatarak sürekli sunucu
güncellemekten veya daha güçlü sunuculara binlerce lira ödemekten
sıyrılabiliriz.
Peki nasıl olacak bu?
Çok basit; milyonlarca yıldır işleyen evrimi taklit ederek.
Parazitlerden kurtularak...
Sunucumuza patır patır gelen robot web-spider isteklerine "erkekseniz
teker teker gelin" diyeceğiz, hepsi o.
Sunucu kayıtlarını inceleyen herkesin bildiği gibi kimi anlarda
çok yoğun bot etkinliği görülür. Üstelik bunların sayısı giderek arttığı
için artık aynı anda istekte bulunup çakışmalara ve
sunucu yükünde ani aşırı artışlara yol açıyorlar.
Bu küçümsememiz gereken bir durum çünkü bize para ziyaretçilere de zaman
kaybettiriyor. Artık çoğu web sitesi / web uygulaması yoğun SQL sorguları
içeriyor. Gerçek bir yarar getirmeyecek arama-motoru / istatistik / telif /
spam / antivirüs / reklam robot ziyaretleri ise hızlı, ardışık ve üst
üste geldiklerinde ziyaretçileri engelleyebilecek düzeyde bir sunucu
yoğunluğuna sebep oluyor. Oysa basit bir trafik lambası ile bunlara
kırmızı ışık yakmamız mümkün.
Aşağıda kolaylıkla kullanabileceğiniz iki işlev (function) bulabilirsiniz.
Hemen hemen her türlü PHP sayfasının başında kullanabilirsiniz.
Sonrasında ise en aşağıda ufak bir robots.txt ipucu var.
Bunların bileşimiyle ben pek çok sunucuda epeyce rahatlama sağlayabildim.
Sizin de sunucu yükünüzü ve bant-genişliğinizi epeyce hafifletecektir.
Kullanacağımız Yoklama, Hızlandırma ve Engelleme İşlevleri
Önce sistem yükünü öğrenelim. İşte loadavg() işlevimiz:
<?php
function loadavg() {
$buffer = "0 0 0";
$f = fopen("/proc/loadavg","rb");
if (!feof($f)) {
$buffer = fgets($f, 1024);
}
fclose($f);
$load = explode(" ",$buffer);
return max((float)$load[0], (float)$load[1], (float)$load[2]);
}
?>
Bunu loadavg() diye çağırdığınızda linux sistemlerde /proc altındaki
loadaverage'ı okuyup en büyük değeri döndürüyor. İlkini, yani o
sıradaki yükü değil de uzun dönem ortalama bile olsa en büyüğünü istememiz
sunucuyu ardışık ani yüklenmelerden korumak için. İlkini kullansaydık
sistem yükünün bizim eşik değerimiz etrafında
bir tür osilasyona girdiğini görebilirdik. Bizse robotlara dur-kalk yaptırmak
değil ani yüklenmelerde
sunucu yükünü dengeli bir azami değerde tutmak istiyoruz.
Gelelim hızlandırma görevi yapan ikinci işlevimize.
Bu işlev PHP içinde normalde kullanılamayan GET_IF_MODIFIED_SINCE türü
HTTP çağrılarını etkin bir biçimde kullanabilmek için.
Web tarayıcıları (Firefox, Opera, Chrome, Internet Explorer, vs.) ile
proxy'ler önbelleklerinde bir sayfa varsa bunun tazeliğini
GET_IF_MODIFIED_SINCE çağrıları ile yoklarlar.
Önbelleklerindeki sayfanın daha önce sunucu tarafından
verilmiş son_değiştirilme (last_modified) tarihini bu çağrı ile
birlikte sunucuya sorarak "eğer bu tarihten daha yeni ise elindekini
gönder bakalım ey sunucu" derler. Sunucu ise eğer bir değişiklik yoksa
"304 Not Modified" yanıtını döndürür. Web tarayıcı veya proxy bu yanıtı
aldığında ise doğrudan ön bellekteki sayfayı kullanır ve sayfayı
indirmekle zaman kaybetmez.
Ancak PHP scriptlerinde ve benzeri diğer CGI dinamik sayfalarda
sunucular last_modified bilgisi göndermez, gönderemez veya ayarlandıysa
sadace o anki zamanı gönderir. Oysa veri tabanında bir yenilik yoksa
o PHP scripti her seferinde aynı sayfayı üretiyor olabilir.
Boşu boşuna her seferinde yeniden çalışacak, onca SQL sorgusu yapacak,
disk kafasını haldır haldır oradan oraya koşturup, işlemcinin önbelleğinin,
işletim sisteminin de context-switch'inin başını ağrıtacaktır.
Gereksiz...
Aşağıdaki script işlevi ile PHP scriptlerimizin başında last_modified ve
expires bilgileri üretip, GET_IF_MODIFIED_SINCE isteklerini
uygun bir dille yanıtlayabiliriz.
Bu işlev kendisine verilen parametre kadar bir zaman boşluğunca
PHP scriptinin değişmediğini bildiriyor. Parametre olarak 2-30 arası
değerler dakika cinsinden içeriğin aynı olacağının bildirildiği süre.
1 değeri ise özel durum ve 1 gün anlamında. Bu dinamik bir script için
uzun bir süre. Yalnızca 1 gün içinde sayfanın değişmeyeceğinin emin
olduğunuz ya da 1 günlük ön belleklemenin sorun yaratmayacağı
durumlarda kullanmak için.
<?php
function hizlan($miktar) {
$agent=$_SERVER['HTTP_USER_AGENT'];
if ( $miktar == 1 ||
preg_match("/bot/i",$agent) ||
preg_match("/Slurp/i",$agent) ||
preg_match("/Twiceler/i",$agent) ) {
$fake_last_modified = gmdate('D, d M Y ', (time())) . "00:00:00 GMT";
$fake_expires = gmdate('D, d M Y ', (time())) . "23:59:59 GMT";
} else {
if ( $miktar < 2 ) $miktar = 2;
if ( $miktar > 30 ) $miktar = 30;
$saat=floor(gmdate('i',(time() - 00))/$miktar)*$miktar;
if ($saat == "0" ) $saat="00";
$sonsaat=floor(gmdate('i',(time() - 00))/$miktar)*$miktar+$miktar;
if ($sonsaat >= 60 ) $sonsaat="59";
$fake_last_modified = gmdate('D, d M Y H:', (time()));
$fake_last_modified .= $saat.":00 GMT";
$fake_expires = gmdate('D, d M Y H:', (time()));
$fake_expires .= $sonsaat.":00 GMT";
}
if ( getenv("HTTP_IF_MODIFIED_SINCE") == $fake_last_modified ) {
header("HTTP/1.1 304 Not Modified");
exit;
}
header('Last-Modified: '.$fake_last_modified);
header('Expires: '.$fake_expires);
}
?>
İşlev verilen dakika miktarına bakarak yalancı bir son değiştirilme
tarihi üretip, o anki çağrı normal bir çağrı ise
Last-Modified HTTP başlığı ile bunu bildiriyor.
Ayrıca bir de aynı süre kadar Expires başlığı üretiyor.
Bu arada bu başlıkları üretip gönderdiği için bu işlevler bir web
sayfası PHP scriptinin en başında çağrılmalı.
Eğer çağrı bir GET-IMS çağrısı ise çağrı tarafından verilen
HTTP_IF_MODIFIED_SINCE değerinin kendisinin üretmiş olduğu
last_modified ile uyuşup uyuşmadığına bakıyor.
Aynıysa HTTP/1.1 304 Not Modified başlığını göndererek
scriptten çıkıyor. Evet sayfayı bir daha ürettirmiyor.
Yalancı son_değiştirme tarihi ise sizin verdiğiniz sürenin en yakınındaki
bir önceki tam katı döndürülüyor. Yani örneğin o an saat 12:21 ise ve siz
dakika miktarı olarak 5 verdi iseniz, last_modified olarak 12:20, expires
olarak da 12:25 döndürüyor. Bu arada dikkat ettiyseniz ortalama
tazelik süresi aslında sizin verdiğinin dakika miktarının yarısı kadar.
Eğer bir çağrı 12:24'te geldiyse 1 dakika sonra süre doluyor. 12:21'de ise
4 dakika sonra. Yani 5 dakika diyerek ortalamada ziyaretçilere son 2.5
dakikalık içeriği sunuyoruz.
Bir forum siteniz varsa, veya bir sosyal imleme veya benzeri bir
toplulukça oluşturulan içeriğe sahip bir siteniz varsa, bu hızlandırma
tekniği ziyaretçilerin sayfadan sayfaya dolaşmalarını epeyce hızlandıracaktır.
Özellikle böyle sitelerde kullanıcılar oradan oraya tıkladıklarından
hızlanma inanılmaz. Hatta sunucu yüküne göre bakarak bu süreyi uzatırsanız
çok daha hızlı yanıt veren bir siteniz olacaktır.
Bu arada fonksiyona eğer miktar olarak 1 değeri verildiyse, sayfanın
gece yarısı 00:00'da güncellendiğini ve gün sonu 23:59'a kadar da güncel
olacağını söyleyecektir. Kimi durumlarda bu oldukça yararlıdır.
Bu işlev bu süreleri siz 1 değeri vermeseniz dahi
user-agent bilgisinden saptadığı robotlara söylüyor ayrıca.
Bu yolla kimi çılgın robotlarla sayfa zararlı mı diye her seferinde
sayfayı indirip yoklamaya çalışan anti-virüs programlarına destur
çekmiş oluyoruz.
PHP Hızlandırma İşlevinin Kullanım Örneği
İlk verdiğimiz sistem yükü işlevi ile birlikte kullanırsak ve
işlevleri include klasörü altına örnekteki dosya adlarıyla kaydettiğimizi
varsayarsak:
<php
// Sayfanın en başı
include("include/function.loadavg.php");
include("include/function.hizlan.php");
$sistemyuku=loadavg();
if ( $sistemyuku > 2 ) {
hizlan(30);
} else if ( $sistemyuku > 1 ) {
hizlan(10);
} else {
hizlan(5);
}
//...
//... sayfanın geri kalan PHP scripti de bundan sonraya
Bu örnekte eğer sistem yükü 2'den çoksa ortalama 15dk, 1-2 arasındaysa
ortalama 5 dakika, 0-1 arasındaysa da ortalama 2.5dk boyunca sayfa değişmiyor
bilgisini verdik. Bu örnek çoğu dinamik site için kullanılabilir. Tabii
bir borsa veya benzeri bir site, hızlı güncellenen bir haber ajansı sitesi
için 5-6 dakikayı geçmenizi önermek olası değil.
Ancak kendi sitenizin durumuna / özelliğine göre bu değerleri
arttırarak verimliliğini arttırmanız mümkün; "varsın insanlar son 5-10
dakikalık içeriği biraz geç görsün" diyebileceğiniz durumlar için...
Uzun bekleme süreleri içinse yüke bakmanıza pek gerek yok. Sadece bir
scriptin başında:
<php
include("include/function.loadavg.php");
include("include/function.hizlan.php");
hizlan(30); // veya 30dk değil tüm gün değişmeyecekse hizlan(1)
dememiz yeterli olacaktır.
Aşırı Yükte Robot Örümcek Durdurma
Şimdi de sıra sitemize yüklenen web-spider'ları geçici olarak durdurmakta.
Önce aşağıdaki scripti include/robotdurdur.php gibi bir adla kaydedelim:
<?php
// Zamana bağlı olsun mu?
$zamanli=false;
// preg_match işlevini güçlendirip array desteği verelim:
function preg_search($ary, $subj) {
$matched = false;
if (is_array($ary)) {
foreach ($ary as $v) {
if (preg_match($v, $subj)) $matched = true;
}
} else {
if (preg_match($ary, $subj) ) $matched = true;
}
return $matched;
}
// IP bulalım:
if ( $_SERVER['HTTP_X_FORWARDED_FOR'] ) {
$ip=$_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip=$_SERVER['REMOTE_ADDR'];
}
$ipp=explode(" ",$ip);
if ( $ipp[count($ipp)-1] != "" ) $ip=str_replace(",","",$ipp[0]);
$agent=$_SERVER['HTTP_USER_AGENT'];
// Belli başlı web-spider'lar (günceli klavyemonitor.com'da):
$needle_sr=array(
"/Spider/i","/Yandex/i","/Crawler/i","/Nutch/i",
"/ScoutJet/i","/Charlotte/i","/Twiceler/i","/bot/i",
"/spider/i","/fastsearch/i","/ia_archiver/i","/Lsearch/i",
"/searchme/i","/Slurp/","/larbin/i","/Pagebull/i",
"/page_verifier/i","/SBIder/i","/GetHTML/i","/StackRambler/i",
"/MMCrawler/i","/sphider/i","/Yeti/i","/touche/i"
);
// Belli başlı web-spider adresleri:
$needle_srip=array(
"/38\.99\.44\.103/","/66\.249\.66\./","/66.249.72.170/",
"/131\.107\.151\./","/66.249.66.161/","/88.131.153.91/",
"/65\.55\.212\./","/65\.54\.188\./","/64\.1\.215\./",
"/217.155.75.171/","/78\.165\.228\./"
);
// Daha ayrıntılı ve güncel liste klavyemonitor . com'da var.
// Eğer $zamanli=true ise bu işlemi yalnızca yoğun saatlerde yapalım:
if ( $zamanli ) {
$zamansaat=date('G');
if ( $zamansaat > 14 && $zamansaat < 19 ) {
if ( preg_search($needle_sr,$agent) || preg_search($needle_srip,$ip) ) {
header(' ',true,403);
exit;
}
}
} else {
if ( preg_search($needle_sr,$agent) || preg_search($needle_srip,$ip) ) {
header(' ',true,403);
exit;
}
}
?>
Şimdi burada $zamanli diye bir değişkenimiz var. Bunu doğrudan scriptin içinde
tanımlıyoruz. Sitenizin kendine özgü durumuna göre bunun değerine siz karar
veriyorsunuz. Eğer sisteme aşırı yük bindiği her durumda robotları
durdurmak istiyorsanız $zamanlı=false; olmalı. Eğer sistem yüklü bile
olsa sadece yoğun site kullanımı olan 15-18 saatleri arasında
durdurulsun istiyorsanız web-spider'lar $zamanli=true; olarak
değiştirebilirsiniz.
include/robotdurdur.php adıyla kaydedeceğimiz bu script user_agent bilgisine
ve IP'sine bakarak robot çağrısı olan istekleri "403 Not Allowed" yanıtı
ile durdurur. Bu yanıt genellikle o gün için o robotu o URL için durdurur.
Ertesi gün reddedildiği sayfayı taramayı yeniden deneyecektir.
Yani bu scripti yalnızca sistem çok yoğun olduğu anlarda çağırırsak
web sitemizi tarayıp dizinlerine almaya çalışan arama motorlarını
küstürmüş olmayız. Hem sitemiz gene arama motorlarındaki sırasını korur
hem de çok yoğun robot taramasına maruz kalmaz.
Kullanmak için tek yapmamız gereken yukarıdaki loadavg(); işlevini
yükledikten ve sistem yükünü ölçtükten sonra belli bir yükte bu işlevi
çağırmak. Önceki örneğin devamına ekleyelim:
<php
// Sayfanın en başı
include("include/function.loadavg.php");
include("include/function.hizlan.php");
$sistemyuku=loadavg();
if ( $sistemyuku > 2 ) {
hizlan(30);
} else if ( $sistemyuku > 1 ) {
hizlan(10);
} else {
hizlan(5);
}
// Aşırı yükte robot durduralım:
if ( $sistemyuku > 2.5 ) include("include/robotdurdur.php");
//...
//... sayfanın geri kalan PHP scripti de bundan sonraya
Bu örneği PHP scriptlerimizin en başına koyarak sistem yüküne göre
önbellekleme sürelerini ve robot isteklerini düzene sokmuş oluyoruz.
Sistem yükü eşik değerleri ile oynayarak ortalama sistem yükünü belli
bir düzeyde tutmanız mümkün. Çoklu sitenin barındığı ortak sunucularda
ise önce sistem yükünü gözleyerek genel ortalama ve uç değerleri
saptayıp ona göre eşik değeri belirleyebilirsiniz. Örneğin tamamıyla
boş ve sadece sizin tek bir sitenizi barındıran bir sunucuda eşik değer olarak
0.20'yi seçebilirsiniz. Veya çok yoğun ortak bir sunucuda yük ortalaması
1'in altına hiç düşmüyor olabilir. Eşik değerini buna göre yukarılara
çekebilirsiniz. Bu ince ayarları yaptıktan sonra sunucu kayıtlarınızı
incelerseniz gerçekten de unique IP azalmamasına rağmen bant-genişliği
kullanımının kayda değer ölçüde düştüğünü görebileceksiniz...
Evet. Son olarak kimi arama motorlarının kullandığı "Crawl-delay" komutunu
robots.txt dosyalarımıza ekleyelim:
User-agent: Slurp
Crawl-delay: 120
User-agent: msnbot
Crawl-delay: 120
User-agent: twiceler
Crawl-delay: 120
User-agent: discobot
Crawl-delay: 120
User-agent: OOZBOT
Crawl-delay: 120
Bu Crawl-delay'e uyan başka robotlara denk gelirseniz onları da
ekleyebilirsiniz.
"User-agent: *" kullanarak hepsi için geçerli derdik ancak GoogleBot dahil
Crawl-delay desteklemeyen kimileri bundan şimdilik şikayet ediyor.
Bu arada ben örnekte 120 saniye değerini verdim. Kendim aslında 360
kullanıyorum.
"Search Engine Optimization" (SEO = Arama Motoru Optimizasyonu)
yapıyor ve "ama sürekli indekslenmek istiyorum" diyebilirsiniz gerçi.
Ancak uzun dönemde bu denli sık yoklanmaya gerek duymazsınız.
Hele sitenizde on binlerce yüz binlerce link varsa
indekslenmeniz hiç bitmeyebilir... Böyle durumlarda arama motorlarının
işlerini uzun süreye yaymak sunucu yükünüzü ve bant genişliğinizi
hafifletecektir. Varsın her saniyede değil de birkaç dakikada bir gelip
indekslesin. Ne de olsa tarar taramaz veritabanlarını güncellemiyorlar...
Evet hepsi bu kadar.
İşinize yaraması dileğiyle.
İlker Fıçıcılar
21 Eylül 2008
Arama önerileri:
bant genişliği,
web sunucu,
işlemci yükü,
işlemci hızı,
bandwidth,
web server,
web sunucu,
sunucu optimizasyonu,
web cache optimizasyonu,
php script,
sunucu hızlandırma,
php script hızlandırma,
mysql oracle sql hızlandırma,
hızlı nternet,
Kaynak gösterecekler için referans:
"Sunucu Yükü ve Bant Genişliği Optimizasyonu",
İlker Fıçıcılar,
http://www.KlavyeMonitor.com/sunucu_yuku_ve_bant_genisligi_optimizasyonu.html
, Eylül 2008
İlgili Benzer Yazılar:
|