
Go 1.27, bağlantının daha hızlı yeniden kullanımı için okunmamış HTTP/1 yanıt gövdelerini otomatik atar
Go 1.27, HTTP/1 bağlantısının yeniden kullanımını iyileştiriyor, okunmamış yanıt gövdelerini otomatik atıyor. index.golang.org üzerinde yapılan testte aynı program Go 1.26'ya göre neredeyse beş kat daha hızlı.
Okunmamış yanıt gövdeleri HTTP/1 bağlantısının yeniden kullanımını engelliyordu
Go'nun net/http paketi HTTP/1.0, HTTP/1.1 ve HTTP/2'yi destekler, bunlar TCP üzerinde çalışır, HTTPS adresleri ise genellikle TLS üzerinde. Yeni bir bağlantı kurmak pahalıdır: TCP el sıkışması bir tam tur süresi (RTT) gerektirir, TLS 1.2 el sıkışması 2 RTT gerektirir ve ancak toplam 3 RTT sonrası ilk HTTP isteği gönderilebilir. Bölgeler arası tek yönlü gecikme sıklıkla 50 milisaniyeyi aşar veya aşar, bu yüzden bağlantı kurulumu küçük bir yanıtın sunumundan çok daha pahalı olabilir.
Bu yüzden HTTP istemcileri ve sunucular mevcut bağlantıları yeniden kullanmaya çalışır. HTTP/1.1'de bağlantılar varsayılan olarak kalıcıdır, ancak yanıtlar aynı bayt akışı üzerinde sırayla gönderilir. Bu, net/http'in mevcut gövdenin sonuna kadar okunmasını bekleyerek bir sonraki yanıtın başlangıcını ancak o zaman bulabileceği anlamına gelir; bu, Content-Length veya Transfer-Encoding başlığı tarafından belirlenir.
Go blog yazısında Nicholas Hussain ve Damien Niall sık yapılan bir hatayı vurgular: http.Get'i çağıran, defer ile resp.Body.Close çağran ve yalnızca durum döndüren, gövde hiç okumayan bir fonksiyon. Go 1.26 ile birlikte, Close çağrıldığında okunmamış gövde kalırsa, net/http bağlantıyı atar ve bir sonraki istek için yeni bir bağlantı açar, böylece kurulum maliyeti yeniden ödenir. Sorun, gövdeyi okuy ancak sonuna kadar eksik okuyan programları da etkiler. Örneğin, encoding/json.Decoder, JSON nesnesini kapanış süslü parantezinde keser, bu yüzden newline ile sonlandıran sunucu o baytı okunmamış bırakır ve bağlantı bir daha kullanılamaz. HTTP/2'de bu sorun yoktur çünkü kareleri tek bağlantıda çoklar ve yanıtları sırayla göndermez.
Go 1.27 gövdeleri otomatik atar
Go 1.27'den itibaren net/http.Transport bunu otomatik olarak halleder. Okunmamış HTTP/1 yanıt gövdesini 50 milisaniye veya 256 kilobayt sınırına kadar asenkron olarak atar, hangi sınır önce gerçekleşiyorsa. Atma işlemi bir sonraki istek gönderilmeden önce tamamlanırsa bağlantı yeniden kullanılır; aksi takdirde yeni bir bağlantı oluşturulur, eski bağlantı ölü bağlantı havuzuna düşer ve gelecek bir istek için yeniden kullanılabilir. Uygulama, yanıtın Connection: close başlığı olduğu durumda atmayı tamamen atlar çünkü bu durumda atma işi anlamsız olurdu.
Yazarlar, bu davranışın Go'nun gelecek sürümlerinde, diğer olası iyileştirmeler ortaya çıktığında değişebileceğini belirtiyorlar.
Kıyaslama Sonuçları ve Öneri
İyileştirme önemlidir. Basit bir durum kontrolü fonksiyonunu 100 kez index.golang.org'a çağıran test programı, dünya genelinde dağıtılmış TLS 1.3 destekli bir siteye, Go 1.26'da yaklaşık 710 milisaniye, Go 1.27'de ise yalnızca yaklaşık 150 milisaniye sürüyor, neredeyse beş kat daha hızlı.
Yeni davranışla, Go ekibi geliştiricilere, HTTP yanıt gövdelerini artık gerekmediğinde, tanıdık defer resp.Body.Close() şablonunu kullanarak basitçe kapatmalarını önerir. Birçok geliştiricinin yıllar boyunca kullandığı, gövdeleri io.Copy ile atma, atılan baytları sınırlama veya atma işlemini timeout ile rekabet gibi manuel tekniklere artık gerek yok. Yazarlar bunu Go'nun sadelik felsefesinin bir parçası olarak görüyor: kod temiz ve basit kalsın, zor kısmı net/http sizin için yapsın.
Kaynaklar: Hacker News
SiTech — AI destekli web geliştirme
Hızlı ve modern web siteleri kuruyor, AI'yı gerçek iş akışlarına taşıyoruz. Projeniz veya sorunuz mu var? Yardımcı olmaktan mutluluk duyarız.