Tepki sürelerinde neden ani bir artış oluyor?


12

IIS'de barındırılan ServiceStack kullanılarak uygulanan bir API'miz var. API'nın yük testini gerçekleştirirken, yanıt sürelerinin iyi olduğunu, ancak sunucu başına yaklaşık 3.500 eşzamanlı kullanıcıyı vurduğumuzda hızla kötüleştiğini keşfettik. İki sunucumuz var ve bunları 7.000 kullanıcıyla vururken ortalama yanıt süreleri tüm uç noktalar için 500ms'nin altındadır. Kutular bir yük dengeleyicinin arkasındadır, bu yüzden sunucu başına 3.500 eşzamanlılık elde ederiz. Ancak toplam eşzamanlı kullanıcı sayısını artırdığımız anda yanıt sürelerinde önemli bir artış görüyoruz. Eşzamanlı kullanıcıları sunucu başına 5.000'e yükseltmek, uç nokta başına ortalama 7 saniyelik ortalama yanıt süresi sağlar.

Sunuculardaki bellek ve CPU oldukça düşüktür, hem yanıt süreleri iyi hem de kötüleştikten sonra. 10.000 eşzamanlı kullanıcıyla zirvede CPU ortalama% 50'nin hemen altındadır ve RAM 16'dan 3-4 GB civarındadır. Aşağıdaki ekran görüntüsü, toplam 10.000 eşzamanlı kullanıcıyla bir yük testi sırasında perfmondaki bazı anahtar sayaçları göstermektedir. Vurgulanan sayaç istek / saniyedir. Ekran görüntüsünün sağında, saniyedeki grafik başına isteklerin gerçekten düzensizleştiğini görebilirsiniz. Bu yavaş yanıt süreleri için ana göstergedir. Bu paterni görür görmez, yük testinde yavaş tepki süreleri görüyoruz.

saniyede isteklerle vurgulanan perfmon ekran görüntüsü

Bu performans sorununu nasıl gideririz? Bunun bir kodlama sorunu mu yoksa yapılandırma sorunu mu olduğunu belirlemeye çalışıyoruz. Web.config veya IIS'de bu davranışı açıklayabilecek herhangi bir ayar var mı? Uygulama havuzu .NET v4.0 çalıştırıyor ve IIS sürümü 7.5. Varsayılan ayarlardan yaptığımız tek değişiklik, uygulama havuzu Kuyruk Uzunluğu değerini 1.000'den 5.000'e güncellemektir. Aspnet.config dosyasına aşağıdaki yapılandırma ayarlarını da ekledik:

<system.web>
    <applicationPool 
        maxConcurrentRequestsPerCPU="5000"
        maxConcurrentThreadsPerCPU="0" 
        requestQueueLimit="5000" />
</system.web>

Daha fazla detay:

API'nın amacı, çeşitli harici kaynaklardan gelen verileri birleştirmek ve JSON olarak döndürmektir. Şu anda veri katmanındaki harici çağrıları önbelleğe almak için bir InMemory önbellek uygulaması kullanıyor. Bir kaynağa yapılan ilk istek, gerekli tüm verileri getirir ve aynı kaynak için sonraki istekler önbellekten sonuç alır. Önbellekteki bilgileri belirli aralıklarla güncelleyen bir arka plan işlemi olarak uygulanan bir 'önbellek çalıştırıcısı' var. Harici kaynaklardan veri alan kodun etrafına kilitleme ekledik. Dış kaynaklardan gelen verileri eşzamansız bir şekilde almak için hizmetleri de uyguladık, böylece uç nokta yalnızca en yavaş harici çağrı kadar yavaş olmalıdır (elbette önbellekte veri yoksa). Bu, System.Threading.Tasks.Task sınıfı kullanılarak yapılır.İşlem için mevcut iş parçacığı sayısı açısından bir sınırlama getirebilir miyiz?


5
CPU'nuzda kaç çekirdek var? Belki de bir çekirdeği maksimize ediyorsunuz. Sihirli sayı% 50,% 25 veya% 12.5 olduğunda, bu, bir çekirdeği en üst düzeye çıkardığınızı ve bir nedenden dolayı boşta duran diğer çekirdekleri kullanamayacağınızı gösterir. Maksimum dışarı çekirdeği kontrol edin.
David Schwartz

1
İstek başına bir iş parçanız var mı? Peki 5000 istek için 5000 iş parçanız var mı? Eğer yaparsanız, bu muhtemelen sizin probleminizdir. Bunun yerine bir iş parçacığı havuzu oluşturmalı ve istekleri iş parçacığı havuzuna geldikçe sıraya koyacak şekilde iş parçacığı havuzunu kullanmalısınız. Bir iş parçacığı bir istekle işini bitirdiğinde, kuyruktaki bir isteği işleyebilir. Bu tür tartışma yığın akışı için en iyisidir. Çok fazla iş parçacığı, çok fazla bağlam anahtarı anlamına gelir.
Matt

1
Burada sadece bir sağlık kontrolü, tüm arka plan işlemlerinizi kapatmayı denediniz ve sadece JSON'un önbellekten statik veri döndürmesi için davranışın ne olduğunu gördünüz mü? Başka bir deyişle, JSON'unuzun statik veri istemesi ve önbelleğinizi tamamen yenileyen "harici zaman uyumsuz çağrıları" kaldırma. Ayrıca, her istekte sunulan JSON verilerinin miktarına bağlı olarak, ağ işlem hacminizi ve sunucuların verileri yeterince hızlı dışarı atamadığı için istekler yedeklenmeye başlayıp başlamadığını düşündünüz mü?
Robert

1
Yukarıdaki Davids önerisine +1. Testi gerçekten tekrar yapmalı ve her bir çekirdek kullanımına dikkatlice bakmalısınız. Başka bir şey yoksa ortadan kaldırmak için bunu en kısa zamanda yapmanızı öneririm. İkincisi, önbelleğinizden biraz şüpheliyim. Kilit çekişmesi tam olarak bu tür bir davranış gösterebilir - bazı kritik nokta kilitlerinde, kilitlerin normalden daha uzun süre tutulmasına neden olan şeylerin hızla yokuş aşağı gittiği bir devrilme noktasına neden olur. Önbellek ve kilit kodunuzu paylaşabilir misiniz?
steve cook

1
Sunucular için disk kurulumu nedir (yük dengelendiklerinden disk kurulumunun aynı olduğunu varsayarsak)? İlk yayınınıza sürücüler / sunucular için tüm özellikleri gönderebilir misiniz? IIS VE IIS günlük dosyalarının bulunduğu fiziksel sürücü (ler) üzerindeki disklere bir perfmon atıyor musunuz? 3.500 istek = 3.500+ IIS günlüğünün girdiği diskte sorun yaşıyor olabilirsiniz. Aynı disk / bölümdeyse, orada büyük bir sorun olabilir.
Techie Joe

Yanıtlar:


2

@DavidSchwartz ve @Matt ile devam eden bir ileti dizisi gibi görünüyor, yönetim sorununu kilitler.

Öneririm:

  1. Harici çağrıları ve onlar için oluşturulan önbelleği dondurun ve sadece sunucu-çevre tarafı ile ilgili olmayan herhangi bir sorunu atmak için yük testini statik harici bilgilerle çalıştırın.

  2. Kullanmıyorlarsa iş parçacığı havuzları kullanın.

  3. Harici aramalar hakkında "Dış kaynaklardan gelen verileri senkronize olmayan bir şekilde almak için hizmetleri de uyguladık, böylece uç nokta yalnızca en yavaş harici arama kadar yavaş olmalıdır (elbette önbellekte veri yoksa). "

Sorular: - Harici arama sırasında veya yalnızca harici arama sonucu önbelleğe yazılırken herhangi bir önbellek verisinin kilitli olup olmadığını kontrol ettiniz mi? (çok açık ama söylemeliyim). - Önbelleğin tamamını veya küçük parçalarını kilitliyor musunuz? (çok açık ama söylemeliyim). - Eşzamansız olsalar bile, harici çağrılar ne sıklıkla çalışır? Çok sık çalıştırılmasalar bile, önbellek kilitliyken önbellekten kullanıcı çağrılarından gelen aşırı miktarda istekle engellenebilirler. Bu senaryo genellikle kullanılan sabit CPU yüzdesini gösterir çünkü birçok iş parçacığı sabit aralıklarla beklemektedir ve "kilitleme" de yönetilmelidir. - Dış görevlerin yavaş senaryo geldiğinde yanıt süresinin de arttığını kontrol ettiniz mi?

Sorun devam ederse, Görev sınıfından kaçınmayı ve dış çağrıları kullanıcı isteklerini yöneten aynı iş parçacığı havuzu aracılığıyla yapmanızı öneririm. Bu, önceki senaryodan kaçınmak içindir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.