|
|
Yayınlandı 14.05.2022 17:11:56
|
|
|
|

Yıllardır HttpClient'ı yanlış kullanıyorum ama sonunda kabus geldi. Web sitem istikrarsızdı ve müşterilerim çok öfkeliydi, basit bir çözümle performans büyük ölçüde arttı ve istikrarsızlık ortadan kaldırıldı.
Aynı zamanda, uygulamamın performansını daha verimli soket kullanımıyla gerçekten geliştirdim.
Mikroservislerle başa çıkmak zor bir sorun olabilir. Daha fazla hizmet eklendikçe ve monolitik uygulamalar parçalandıkça, hizmetler arasında iletişim yolları giderek artmaya eğilimlidir. Birçok iletişim seçeneği vardır, ancak HTTP çok popüler bir seçenektir. Mikroservis C# veya herhangi bir .NET dilinde yerleşik ise, muhtemelen zaten HttpClient kullanıyorsunuzdur.
Sorun şu
Using ifadesi, tek seferlik nesneleri yöneten bir C# özelliğidir. Kullanım bloğu tamamlandığında, tek seferlik nesne (bu durumda HttpClient) kapsam dışı olur ve elden çıkar. İmha yöntemini çağırın ve kullanılan kaynakları temizleyin. Bu, .NET'te veritabanından akış yazarına kadar her şey için kullandığımız çok tipik bir desendir. Aslında, temizlenmesi gereken harici bir kaynağı olan herhangi bir nesne, o IDisposable arayüzü kullanır.
Ve bunu kullanmak istediğin için suçlanamazsın. İlk olarak, bunu yapmak iyi bir uygulama olarak kabul edilir. Aslında, Microsoft'un resmi dokümantasyonu şunları kullanıyor:
Genel olarak, IDisposable bir nesne kullanılırken, using ifadesinde bildirilmeli ve örneklenmelidir. İkincisi, gördüğünüz tüm kodlar...... HttpClient'ın başı, site ASP.NET en güncel dokümantasyonu dahil olmak üzere using statement bloğunu kullanmanızı söyler. Aynı şey internetteki makalede de söylenir.
Ama HttpClient farklı. IDisposable arayüzü uygulasa da, aslında paylaşılan bir nesnedir. Bu, perde arkasında yeniden giriş ve konu için güvenli olduğu anlamına gelir. Her çalıştırma için yeni bir örnek oluşturmak yerine, uygulamanızın ömrü boyunca bir HttpClient örneğini paylaşmalısınız. HttpClient, nedenini görelim.
Kendin görün
İşte HttpClient'ı göstermek için basit bir program:
Bu adres şu adrese yönlendirilecektir http://aspnetmonsters.com10 istek açıp GET yapıyoruz, sadece durum kodunu yazdırıyoruz, böylece çalıştığını biliyoruz. Çıktı şu olacak:
Bekle, daha fazlası var!
Her şey ve her şey dünya için doğru olur. ama öyle değil. Netstat aracını çıkarıp onu çalıştıran makinedeki soket durumuna bakarsak, şunları görürüz:
C:\code\socket>NETSTAT.EXE ... Proto Yerel Adres Yabancı Adres Durumu TCP 10.211.55.6:12050 waws-prod-bay-017:http TIME_WAIT TCP 10.211.55.6:12051 waws-prod-bay-017:http TIME_WAIT TCP 10.211.55.6:12053 waws-prod-bay-017:http TIME_WAIT TCP 10.211.55.6:12054 waws-prod-bay-017:http TIME_WAIT TCP 10.211.55.6:12055 waws-prod-bay-017:http TIME_WAIT TCP 10.211.55.6:12056 waws-prod-bay-017:http TIME_WAIT TCP 10.211.55.6:12057 waws-prod-bay-017:http TIME_WAIT TCP 10.211.55.6:12058 waws-prod-bay-017:http TIME_WAIT TCP 10.211.55.6:12059 waws-prod-bay-017:http TIME_WAIT TCP 10.211.55.6:12060 waws-prod-bay-017:http TIME_WAIT TCP 10.211.55.6:12061 waws-prod-bay-017:http TIME_WAIT TCP 10.211.55.6:12062 waws-prod-bay-017:http TIME_WAIT TCP 127.0.0.1:1695 SIMONTIMMS742B:1696 KURULDU ... Garip...... Uygulama kapatıldı, ancak ASP.NET Monsters web sitesini barındıran Azure makinesine hala açık birçok bağlantı var. GirdilerTIME_WAITdurum, yani bağlantının bir tarafında (bizimki) kapatıldığını gösteriyor, ancak ağda bir yerde gecikmeli olabileceği için başka paketlerin gelip gelmediğini görmek için hâlâ bekliyoruz. İşte TCP/IP durumunun bir diyagramı:
Windows bu durumda 240 saniye boyunca bağlı kalır ([HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpTimedWaitDelay] ayarıyla ayarlandığı gibi). Windows'un yeni bir soketi ne kadar hızlı açabileceğinize dair bir sınırı var, bu yüzden bağlantı havuzlarınız biterse böyle bir hata görebilirsiniz:
Uzak sunucuya bağlanamıyor
System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted. Google'da arama yaparsanız, bağlantı zaman duruşunu azaltmak için kötü tavsiyeler verir. Aslında, HttpClient veya benzer şekilde oluşturulmuş bir uygulama ile bir sunucuda doğru çalışırken, zaman aşımlarının azaltılması başka olumsuz sonuçlara yol açabilir. "Doğru"nun ne anlama geldiğini anlamalı ve temel sorunu çözmemiz gerekiyor, makine düzeyindeki değişkenlerle uğraşmamalıyız.
Düzelt
Bir HttpClient örneğini paylaşırsak, soket israfını tekrar kullanarak azaltabiliriz:
Tüm uygulama için sadece bir ortak örnek olduğunu unutmayın. HttpClient hâlâ eskisi gibi çalışıyor (aslında soket yeniden kullanımı nedeniyle biraz daha hızlı). Netstat artık sadece şunları gösteriyor:
TCP 10.211.55.6:12254 waws-prod-bay-017:http KURULDU Üretim senaryosunda soket sayım ortalama 4000 civarında ve 5000'in üzerinde en yüksek seviyeye ulaşıyor, bu da sunucudaki mevcut kaynakları sıkıştırıyor ve servisin çökmesine neden oluyor. Değişiklik uygulandıktan sonra, kullanılan soket sayısı ortalama 4000'den sürekli olarak 400'ün altına düştü, genellikle 100 civarına düştü.
Bu, izleme aracımızdan alınan ve belirli sayıda düzeltme kanıtı belirli sayıda mikroservise dağıttıktan sonra ne olduğunu gösteren bir grafikin parçasıdır.
Dramatikti. Herhangi bir yük türü varsa, şu iki şeyi aklınızda tutmalısınız:
HttpClient cihazınızı statik yapın. Belirli bir davranış (örneğin hizmetinizin başarısız olmasına sebep olmak gibi) aradığınız sürece kullanımınızı çöpe atmayın veya paketlemeyin. HttpClient
özet
Aylarca mücadele ettiğimiz soket tükenmesi sorunu ortadan kalktı ve müşterilerimiz sanal bir geçit töreni yapıyor. Bu hatanın ne kadar belirgin olmadığını küçümseyemem. Yıllar içinde uygulanan nesnelerle, IDisposable'le uğraşmaya alıştık ve R# ile CodeRush gibi birçok refaktör aracı aslında bunu yapmazsanız sizi uyarıyor. Bu durumda, HttpClient'ı ortadan kaldırmak yanlış bir yaklaşımdır. HttpClient IDisposable uygular ve kötü davranışları teşvik eder bu talihsiz
Özgün:Bağlantı girişi görünür.
|
Önceki:ASP.NET Core, IIS'de Süreç İçi ve Süreç Dışı modelleri barındırırÖnümüzdeki:ASP.NET Core (XV), HTTP istekleri göndermek için HttpClient kullanır
|