Performans ayarlama - Birden çok arka uç hizmeti

Azure Kubernetes Service (AKS)
Azure Cosmos DB

Bu makalede, bir geliştirme ekibinin performans sorunlarını bulmak ve dağıtılmış bir sistemin performansını artırmak için ölçümleri nasıl kullandığı açıklanmaktadır. Makale, örnek bir uygulama için yapılan gerçek yük testini temel alır. Uygulama, sonuçları oluşturmak için kullanılan Visual Studio yük testi projesiyle birlikte mikro hizmetler için Azure Kubernetes Service (AKS) Temeli'nden alınır.

Bu makale, bir serinin bir parçasıdır. buradaki ilk bölümü okuyun.

Senaryo: Bilgileri almak ve sonuçları toplamak için birden çok arka uç hizmetini çağırın.

Bu senaryo bir insansız hava aracı teslim uygulamasını içerir. İstemciler en son fatura bilgilerini almak için REST API'sini sorgulayabilir. Faturada müşterinin teslimatlarının, paketlerinin ve toplam insansız hava aracı kullanımının özeti yer alır. Bu uygulama AKS üzerinde çalışan bir mikro hizmet mimarisi kullanır ve fatura için gereken bilgiler birkaç mikro hizmete yayılır.

Uygulama, istemcinin her hizmeti doğrudan çağırması yerine Ağ Geçidi Toplama desenini uygular. İstemci bu düzeni kullanarak bir ağ geçidi hizmetine tek bir istekte bulunur. Ağ geçidi de arka uç hizmetlerini paralel olarak çağırır ve ardından sonuçları tek bir yanıt yükünde toplar.

Ağ Geçidi Toplama desenini gösteren diyagram

Test 1: Temel performans

Bir temel oluşturmak için geliştirme ekibi, toplam 8 dakika boyunca bir sanal kullanıcıdan 40 kullanıcıya kadar yükü artırarak adım yükleme testiyle başladı. Visual Studio'dan alınan aşağıdaki grafik sonuçları gösterir. Mor çizgi kullanıcı yükünü, turuncu çizgi ise aktarım hızını (saniye başına ortalama istek sayısı) gösterir.

Visual Studio yük testi sonuçlarının grafiği

Grafiğin alt kısmındaki kırmızı çizgi, istemciye hata döndürülmedi ve bu da teşvik edici bir durumdur. Ancak ortalama aktarım hızı testin yarısında zirveye çıkar ve yük artmaya devam etse bile kalan süre boyunca düşer. Bu, arka ucun yetişemediğini gösterir. Burada görülen desen, bir sistem kaynak sınırlarına ulaşmaya başladığında yaygındır; maksimuma ulaştıktan sonra aktarım hızı gerçekten önemli ölçüde düşer. Kaynak çekişmesi, geçici hatalar veya özel durumların oranındaki artış bu desene katkıda bulunabilir.

Şimdi sistemde neler olduğunu öğrenmek için izleme verilerini inceleyelim. Sonraki grafik Application Insights'tan alınmıştır. Ağ geçidinden arka uç hizmetlerine yapılan HTTP çağrılarının ortalama sürelerini gösterir.

HTTP çağrı sürelerinin grafiği

Bu grafik, GetDroneUtilizationözellikle bir işlemin (ortalama olarak çok daha uzun sürdüğünü) bir büyüklük sırasına göre gösterir. Ağ geçidi bu çağrıları paralel olarak yapar, bu nedenle en yavaş işlem isteğin tamamının tamamlanmasının ne kadar süreceğini belirler.

Bir sonraki adım, işlemi ayrıntılı olarak incelemek GetDroneUtilization ve herhangi bir performans sorunu aramaktır. Bu olasılıklardan biri kaynak tükenmesi olabilir. Bu belirli arka uç hizmetinin CPU veya belleği tükeniyor olabilir. Aks kümesi için bu bilgiler Azure İzleyici kapsayıcı içgörüleri özelliği aracılığıyla Azure portal sağlanır. Aşağıdaki grafiklerde küme düzeyinde kaynak kullanımı gösterilmektedir:

AKS düğümü kullanımı grafiği

Bu ekran görüntüsünde, hem ortalama hem de maksimum değerler gösterilir. Ortalama, verilerdeki ani artışları gizleyebileceğinden, yalnızca ortalamadan daha fazlasına bakmak önemlidir. Burada ortalama CPU kullanımı %50'nin altında kalır ancak %80'e varan birkaç ani artış vardır. Bu, kapasiteye yakın ancak yine de toleranslar dahilindedir. Performans sorununa başka bir şey neden oluyor.

Sonraki grafikte gerçek suçlu ortaya çıkar. Bu grafik, Teslim hizmetinin arka uç veritabanındaki HTTP yanıt kodlarını gösterir ve bu durumda Azure Cosmos DB'dir. Mavi çizgi başarı kodlarını (HTTP 2xx), yeşil çizgi ise HTTP 429 hatalarını temsil eder. HTTP 429 dönüş kodu, çağıran sağlanandan daha fazla kaynak birimi (RU) tüketdiğinden Azure Cosmos DB'nin istekleri geçici olarak azaltması anlamına gelir.

Kısıtlanmış isteklerin grafiği

Geliştirme ekibi, daha fazla içgörü elde etmek için Application Insights'ı kullanarak temsili bir istek örneği için uçtan uca telemetri verilerini görüntüledi. Bir örnek aşağıdadır:

Uçtan uca işlem görünümünün ekran görüntüsü

Bu görünüm, zamanlama bilgileri ve yanıt kodlarıyla birlikte tek bir istemci isteğiyle ilgili çağrıları gösterir. Üst düzey çağrılar ağ geçidinden arka uç hizmetlerine yapılır. çağrısı GetDroneUtilization , dış bağımlılıklara ( bu örnekte Azure Cosmos DB'ye) yapılan çağrıları gösterecek şekilde genişletilir. Kırmızı renkli çağrı http 429 hatası döndürdü.

HTTP 429 hatası ile sonraki çağrı arasındaki büyük boşluğu not edin. Azure Cosmos DB istemci kitaplığı http 429 hatası aldığında otomatik olarak geri döner ve işlemi yeniden denemek için bekler. Bu görünümün gösterdiği, bu işlemin 672 ms boyunca, bu sürenin büyük bir kısmını Azure Cosmos DB'yi yeniden denemek için beklemek için harcandığıdır.

Bu analiz için başka bir ilginç grafik aşağıdadır. Fiziksel bölüm başına RU tüketimini ve fiziksel bölüm başına sağlanan RU'ları gösterir:

Bölüm başına RU tüketimi grafiği

Bu grafı anlamak için Azure Cosmos DB'nin bölümleri nasıl yönettiğini anlamanız gerekir. Azure Cosmos DB'deki koleksiyonların bölüm anahtarı olabilir. Her olası anahtar değeri, koleksiyondaki verilerin mantıksal bir bölümünü tanımlar. Azure Cosmos DB bu mantıksal bölümleri bir veya daha fazla fiziksel bölüme dağıtır. Fiziksel bölümlerin yönetimi Azure Cosmos DB tarafından otomatik olarak işlenir. Daha fazla veri depoladıkça Azure Cosmos DB, yükü fiziksel bölümlere yaymak için mantıksal bölümleri yeni fiziksel bölümlere taşıyabilir.

Bu yük testi için Azure Cosmos DB koleksiyonu 900 RU ile sağlandı. Grafikte fiziksel bölüm başına 100 RU gösterilir ve bu da toplam dokuz fiziksel bölüm anlamına gelir. Azure Cosmos DB fiziksel bölümlerin parçalanması işlemini otomatik olarak işlese de, bölüm sayısını bilmek performans hakkında içgörü sağlayabilir. Geliştirme ekibi, iyileştirmeye devam ettikçe bu bilgileri daha sonra kullanacaktır. Mavi çizginin mor yatay çizgiyi aşması durumunda RU tüketimi sağlanan RU'ları aşmıştır. Bu noktada Azure Cosmos DB çağrıları kısıtlamaya başlar.

Test 2: Kaynak birimlerini artırma

İkinci yük testi için ekip, Azure Cosmos DB koleksiyonunun ölçeğini 900 RU'dan 2500 RU'ya çıkardı. Aktarım hızı 19 istekten/saniyeden 23 istek/saniyeye yükseltildi ve ortalama gecikme süresi 669 ms'den 569 ms'ye düştü.

Ölçüm Test 1 Test 2
Aktarım hızı (req/sn) 19 23
Ortalama gecikme süresi (ms) 669 569
Başarılı istekler 9,8 K 11 K

Bunlar büyük kazançlar değildir, ancak zaman içinde grafiğe baktığımızda daha eksiksiz bir resim gösterilir:

Daha tutarlı aktarım hızı gösteren Visual Studio yük testi sonuçlarının grafiği.

Önceki testte ani bir artış ve ardından keskin bir düşüş gösterildi, ancak bu test daha tutarlı aktarım hızı gösteriyor. Ancak en yüksek aktarım hızı önemli ölçüde yüksek değildir.

Azure Cosmos DB'ye yapılan tüm istekler 2xx durumu döndürdü ve HTTP 429 hataları ortadan gitti:

Azure Cosmos DB çağrılarının grafiği

RU tüketimi ve sağlanan RU'lar grafiği, çok fazla alan olduğunu gösterir. Fiziksel bölüm başına yaklaşık 275 RU vardır ve yük testi saniyede tüketilen yaklaşık 100 RU'da zirveye çıktı.

Ru tüketiminin ve sağlanan RU'ların çok fazla yer olduğunu gösteren grafiği.

Bir diğer ilginç ölçüm de başarılı bir işlem için Azure Cosmos DB'ye yapılan çağrıların sayısıdır:

Ölçüm Test 1 Test 2
İşlem başına çağrı sayısı 11 9

Hata olmadığı varsayıldığında, çağrı sayısı gerçek sorgu planıyla eşleşmelidir. Bu durumda, işlem dokuz fiziksel bölümün tümüne isabet eden bir çapraz bölüm sorgusu içerir. İlk yük testindeki daha yüksek değer, 429 hatası döndüren çağrı sayısını yansıtır.

Bu ölçüm, özel bir Log Analytics sorgusu çalıştırılarak hesaplandı:

let start=datetime("2020-06-18T20:59:00.000Z");
let end=datetime("2020-07-24T21:10:00.000Z");
let operationNameToEval="GET DroneDeliveries/GetDroneUtilization";
let dependencyType="Azure DocumentDB";
let dataset=requests
| where timestamp > start and timestamp < end
| where success == true
| where name == operationNameToEval;
dataset
| project reqOk=itemCount
| summarize
    SuccessRequests=sum(reqOk),
    TotalNumberOfDepCalls=(toscalar(dependencies
    | where timestamp > start and timestamp < end
    | where type == dependencyType
    | summarize sum(itemCount)))
| project
    OperationName=operationNameToEval,
    DependencyName=dependencyType,
    SuccessRequests,
    AverageNumberOfDepCallsPerOperation=(TotalNumberOfDepCalls/SuccessRequests)

Özetlemek gerekirse, ikinci yük testi iyileştirmeyi gösterir. Ancak, GetDroneUtilization işlem yine de bir sonraki en yavaş işlemden daha uzun bir büyüklük sırası alır. Uçtan uca işlemlere bakmak nedenlerini açıklamaya yardımcı olur:

İyileştirmeyi gösteren ikinci yük testinin ekran görüntüsü.

Daha önce belirtildiği gibi, GetDroneUtilization işlem Azure Cosmos DB'ye çapraz bölüm sorgusu içerir. Bu, Azure Cosmos DB istemcisinin sorguyu her fiziksel bölüme yaymak ve sonuçları toplamak zorunda olduğu anlamına gelir. Uçtan uca işlem görünümünde gösterildiği gibi, bu sorgular seri olarak gerçekleştirilir. İşlem tüm sorguların toplamı kadar sürer ve verilerin boyutu arttıkça ve daha fazla fiziksel bölüm eklendikçe bu sorun daha da kötüleşir.

Test 3: Paralel sorgular

Önceki sonuçlara bağlı olarak, gecikme süresini azaltmanın belirgin bir yolu sorguları paralel olarak vermektir. Azure Cosmos DB istemci SDK'sı, en yüksek paralellik derecesini denetleen bir ayara sahiptir.

Değer Açıklama
0 Paralellik yok (varsayılan)
> 0 En fazla paralel çağrı sayısı
-1 İstemci SDK'sı en uygun paralellik derecesini seçer

Üçüncü yük testi için bu ayar 0'dan -1'e değiştirildi. Aşağıdaki tabloda sonuçlar özetlemektedir:

Ölçüm Test 1 Test 2 Test 3
Aktarım hızı (req/sn) 19 23 42
Ortalama gecikme süresi (ms) 669 569 215
Başarılı istekler 9,8 K 11 K 20 K
Kısıtlanmış istekler 2,72 K 0 0

Yük testi grafiğinden yalnızca genel aktarım hızı çok daha yüksek (turuncu çizgi) değil, aynı zamanda aktarım hızı da yüke (mor çizgi) ayak uyduruyor.

Yüke ayak uyduran daha yüksek genel aktarım hızını gösteren Visual Studio yük testi sonuçlarının grafiği.

Uçtan uca işlem görünümüne bakarak Azure Cosmos DB istemcisinin paralel sorgular yaptığını doğrulayabiliriz:

Azure Cosmos DB istemcisinin paralel sorgular yaptığını gösteren uçtan uca işlem görünümünün ekran görüntüsü.

İlginçtir ki, aktarım hızını artırmanın bir yan etkisi, saniyede tüketilen RU sayısının da artmasıdır. Azure Cosmos DB bu test sırasında istekleri kısıtlamasa da, tüketim sağlanan RU sınırına yakındı:

Sağlanan RU sınırına yakın RU tüketiminin grafiği.

Bu grafik, veritabanının ölçeğini daha da genişletmeye ilişkin bir sinyal olabilir. Ancak bunun yerine sorguyu iyileştirebileceğimiz ortaya çıktı.

4. Adım: Sorguyu iyileştirme

Önceki yük testi gecikme süresi ve aktarım hızı açısından daha iyi performans gösterdi. Ortalama istek gecikme süresi %68 azaltıldı ve aktarım hızı %220 arttı. Ancak bölümler arası sorgu önemli bir konudur.

Bölümler arası sorgularla ilgili sorun, her bölümde RU için ödeme yaptığınızdır. Sorgu yalnızca zaman zaman (örneğin saatte bir) çalıştırılıyorsa, bunun bir önemi olmayabilir. Ancak, bölümler arası sorgu içeren yoğun okuma içeren bir iş yükü gördüğünüzde, bölüm anahtarı ekleyerek sorgunun iyileştirilip iyileştirilemeyeceğini görmeniz gerekir. (Farklı bir bölüm anahtarı kullanmak için koleksiyonu yeniden tasarlamanız gerekebilir.)

Bu senaryonun sorgusu aşağıdadır:

SELECT * FROM c
WHERE c.ownerId = <ownerIdValue> and
      c.year = <yearValue> and
      c.month = <monthValue>

Bu sorgu, belirli bir sahip kimliği ve ay/yıl ile eşleşen kayıtları seçer. Özgün tasarımda, bu özelliklerden hiçbiri bölüm anahtarı değildir. Bunun için istemcinin sorguyu her fiziksel bölüme yayma ve sonuçları toplaması gerekir. Sorgu performansını geliştirmek için geliştirme ekibi, koleksiyonun bölüm anahtarı sahip kimliği olacak şekilde tasarımı değiştirdi. Bu şekilde, sorgu belirli bir fiziksel bölümü hedefleyebilir. (Azure Cosmos DB bunu otomatik olarak işler; bölüm anahtarı değerleriyle fiziksel bölümler arasındaki eşlemeyi yönetmeniz gerekmez.)

Koleksiyonu yeni bölüm anahtarına değiştirdikten sonra RU tüketiminde önemli bir gelişme oldu ve bu da doğrudan daha düşük maliyetlere çevrildi.

Ölçüm Test 1 Test 2 Test 3 Test 4
İşlem başına RU sayısı 29 29 29 3.4
İşlem başına çağrı sayısı 11 9 10 1

Uçtan uca işlem görünümü, tahmin edildikçe sorgunun yalnızca bir fiziksel bölümü okuduğunu gösterir:

Sorgunun yalnızca bir fiziksel bölümü okuduğunu gösteren uçtan uca işlem görünümünün ekran görüntüsü.

Yük testi gelişmiş aktarım hızını ve gecikme süresini gösterir:

Ölçüm Test 1 Test 2 Test 3 Test 4
Aktarım hızı (req/sn) 19 23 42 59
Ortalama gecikme süresi (ms) 669 569 215 176
Başarılı istekler 9,8 K 11 K 20 K 29 K
Kısıtlanmış istekler 2,72 K 0 0 0

İyileştirilmiş performansın bir sonucu olarak düğüm CPU kullanımının çok yüksek olması gerekir:

Yüksek düğüm CPU kullanımını gösteren grafik.

Yük testinin sonuna doğru ortalama CPU yaklaşık %90'a, maksimum CPU ise %100'e ulaştı. Bu ölçüm, CPU'un sistemde bir sonraki performans sorunu olduğunu gösterir. Daha yüksek aktarım hızı gerekiyorsa, sonraki adım Teslim hizmetinin ölçeğini daha fazla örneğe genişletme olabilir.

Özet

Bu senaryo için aşağıdaki performans sorunları belirlendi:

  • Sağlanan RU sayısı yetersiz olduğundan Azure Cosmos DB azaltma istekleri.
  • Birden çok veritabanı bölümünü seri olarak sorgulamanın neden olduğu yüksek gecikme süresi.
  • Sorgu bölüm anahtarını içermediğinden verimsiz bölümler arası sorgu.

Buna ek olarak, CPU kullanımı daha yüksek ölçekte olası bir performans sorunu olarak belirlendi. Geliştirme ekibi bu sorunları tanılamak için şunları inceledi:

  • Yük testinden gecikme süresi ve aktarım hızı.
  • Azure Cosmos DB hataları ve RU tüketimi.
  • Application Insight'daki uçtan uca işlem görünümü.
  • Azure İzleyici kapsayıcı içgörülerinde CPU ve bellek kullanımı.

Sonraki adımlar

Performans kötü modellerini gözden geçirme