Bilindiği üzere HTTP bir ağ protokolüdür. Açılımı
Hyper Text Transfer Protokol'dür. HTML ve resim gibi bir çok kaynağın
ağ üzerinden paylaşılmasına imkan verir. Üzerinde paylaşıma açık
kaynakları barındıran ve istek bekleyen yapıya Server,
bu kaynakları talep eden yapıya ise Client adı
verilir. Client ile Server
arasındaki bu paylaşım HTTP protoklü sayesinde
gerçekleşir. Client bu protokol üzerinden bir request gönderir. Server da bu request'i işleyerek Client'a uygun
bir response döndürür. Bir çok kişi tarafından bilinen bu kısa özetten
sonra şunu sormak gerekir. Peki bu iletişim nasıl başlatılır, nasıl
devam eder ve nasıl sonlanır.
Connection per Request
HTTP/1.0 (RFC-1945) spesifikasyonu 1996 yılında
duyuruldu. Bu spesifikasyon ile default olarak Client
ile Server arasında her request zamanında yeni bir
connection açılması öngörülmüştür. Böylece Connection
per Request kavramı kullanılmıştır. Client Server'dan
herhangi bir kaynak talep edeceği zaman bir connection açılır ve Client request'i bu connection aracılığıyla Server'a gönderir. Server ilgili
request'e karşılık bir response üreterek bunu Client'a
yine aynı connection üzerinden gönderir ve connection sonlandırılır. Connection açmak CPU yoğun ve
beklemeyi artıran bir etkendir.
Persistent Connections
Başlangıçta request ve response'lar
bugünkü durumla karşılaştırıldığında, daha basit ve birbirini izleyen
request sayıları düşük olduğundan connection per request yöntemine
gidilmişti. Fakat ilerleyen yıllarda sunulan kaynakların yapıları daha
karmaşık olmaya ve ana request'ten sonra aynı sayfanın tam anlamıyla
götüntülenebilmesi için ardışık request ve response'lar zinciri
ihtiyacı doğmaya başlayınca, persistent connection
kavramı kullanılmaya başlandı. HTTP 1.0 spessifikasyonunda persistent connection'ın nasıl ele alınacağı ile
ilgili bir ifade yoktu. Zaten HTTP protokolü
temelde her request ve response için tek bir connection kullanılması
üzerinde kurulmuştu.
HTTP/1.0 spesifikasyonunda persistent
connection'a yer verilmemesine karşın genişletilmiş HTTP/1.0
protokolünde bazı implementasyonlar Connection:
Keep-Alive header'ını kullanarak persistent connection'ı ela aldılar.
Client bir request göndereceği zaman header'a bir Connection: Keep-Alive header'ını ekler. Server böyle bir header'la karşılaştığında Client'ın persistent connection kurmak istediğini
anlar. Eğer Server implementasyonu persistent
connection'ı destekliyorsa bir response üreterek yine header'ına Connection: Keep-Alive header'ını ekleyerek Client'a gönderir. Bundan sonra Client'la
Server arasındaki mütakip iletişim bu connection
aracılığıyla gerçekleştirilir. Fakat her iletişimde Connection:
Keep-Alive header'ının bulunma zorunluluğu vardır. Eğer Client request header'ında Connection:
Keep-Alive header'ını göndermezse Server
connection'ı sonlandırır.
Client eğer HTTP/1.0+Keep-Alive protokolü ile bir Proxy
üzerinden persistent
conenction, yapmaya çalıştığında, bazı çıkmazlara neden olabilmektedir.
Şöyle ki: Client "Connection: Keep-Alive" header'ını
barındıran bir requesti Proxy'e gönderdiğinde HTTP/1.0 protokolü ile
çalışan eski proxy'ler bu header'ı tanımayabilir ve header'a herhangi
bir müdahele yapmadan Sever'a bu isteği iletir. Server header'ı
gördüğünde Client'ın (aslında Server için client proxy'dir.)
persistent connection yapmak istediğini düşünür. Bunun üzerine
response'u, "Connection: Keep-Alive" header'ını yazarak client olarak
gördüğü Proxy sunucusuna gönderir ve connection'ı kapatmaz. Yine Proxy
request için yaptığını, response için de yaparak header'ı
anlayamadığından aynı şekilde Client'a gönderir. Client da Server'ın
(Client için Server Proxy dir) persistent connection'ı kabul ettiğini
düşünür. Bu durumda bir sonraki isteğini de aynı connection üzerinden
göndermeye çalışır, fakat bu connection Proxy tarafından çoktan
kapatılmıştır bile. Request başarılı olmaz. Proxy de benzer bir şekilde
connection'ın sunucu tarafından kapatılmasını bekler, fakat Server
persistent connection yaptığını düşündüğünden connection kapatılmaz,
taki timeout olana kadar. Bu da Proxy ve Server tarafında gereksiz bir
kaynak israfına daha sonraları da çalışamaz hale gelmesine neden
olabilir.
HTTP/1.1 protoklü'nde (RFC-2068) (1997) ise
persistent connection default olarak kullanılır ve başlatılması için
herhangi bir header'a gerek duyulmaz. Eğer sunucu persistent
connection'ı destekliyorsa açılan connection Client ve Server
arasında mütakip request ve response'lar için kullanılır, taki Server
connection'ın kapatılacağını bildiren Connection: close header'ını son
response'a ekleyene kadar. Persistent conenction'ın kullanılmasının,
her request'te yeni bir conenction açma maliyetinden kaçınmak, CPU
kullanım oranını, network tıkanıklığını ve bekleme sürelerini daha aza
indirmek gibi avantajları vardır. Özellikle secure iletişimde daha
fazla CPU ihtiyacı olacağından dolayı persistent connection'ın
avantajı daha önemli hale gelmektedir.
Server tarafında request işleme
yöntemleri
Buraya kadar anlatılanlar sadece Client ve Server
arasında connection açılması ve ikisi arasında iletişimin nasıl
yapılacağı ile ilgiliydi. Bundan sonraki ele alınması gereken konu ise
gelen request'in Server tarafında en etkili şekilde nasıl
işleneceğidir.
Server tarafında requestlerin işlenmesi için
genelde bir thread havuzu bulundurulur. Her bir request için yeni bir
process açmak yerine thread mantığının kullanılması performas
açısından daha iyidir. Bir de bu thread'lerin bir havuzda toplanıldığı
düşünüldüğünde her defasında yeni bir thread açma maliyetinden de
kurtulunmuş olur, böylece daha hızlı cevap verilebilir.
İlk zamanlar her bir connection (persistent connection için Client olarak düşünülebilir) için
Server tarafında bir thread tahsis edilir, connection kapatıldığında
bu thread havuza tekrar iade edilir ve yeni bir client'ın kullanımına
hazır hale gelirdi, Fakat bir Client'ın yaptığı request sayısının
genelde sınırlı ve belirli aralıklarla olduğu düşünüldüğünde, arada
geçen zaman diliminde Client için tahsis edilen thread boş bir şekilde
sadece o Client'dan gelecek istekleri bekmek durumunda kalacaktır.
Kullanılan bu request işleme metoduna thread per connection ismi
verilmektedir. Bu yöntem hayli maliyetli bir yöntem olduğundan daha
sonra thread per request metodu düşünülmüştür. Bu yöntem
kullanıldığında her persistent connection için bir thread tahsis etmek
yerine her bir request için (farklı farklı connectionlardan) bir
thread tahsis edilir ve request için response dönüldüğü anda bir
sonraki request için kullanılmak üzere thread havuzuna iade edilir.
Böylelikle Server kaynaklarından olabildiğince yararlanılmış olur.
Kaynaklar:
http://www8.org/w8-papers/5c-protocols/key/key.html
https://www.safaribooksonline.com/library/view/http-the-definitive/1565925092/ch04s05.html
http://en.wikipedia.org/wiki/HTTP_persistent_connection
http://www.jmarshall.com/easy/http/
Bahattin hocam eline sağlık.....
YanıtlaSil