25 Ocak 2015 Pazar

HTTP Persistent Connections

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/

1 yorum :