Performans ayarlama senaryosu: Azure Işlevleri ile olay akışı
Bu makalede, bir geliştirme ekibinin, performans sorunlarını bulmak ve dağıtılmış bir sistemin performansını geliştirmek için ölçümleri nasıl kullandığı açıklanır. Makale, örnek bir uygulama için yaptığımız gerçek yük testini temel alır.
Bu makale, bir serinin bir parçasıdır. Buradailk parçayı okuyun.
Senaryo: Azure işlevleri kullanarak olay akışını işleme.

Bu senaryoda, bir karones, konum verilerini gerçek zamanlı olarak Azure IoT Hub gönderir. işlevler uygulaması olayları alır, verileri geojson biçimine dönüştürür ve dönüştürülen verileri Cosmos DB yazar. Cosmos DB jeo-uzamsal verileriçin yerel destek içerir ve Cosmos DB koleksiyonlarının etkin uzamsal sorgular için dizini oluşturulabilir. Örneğin, bir istemci uygulaması belirli bir konumun 1 km dahilinde tüm dronlarla 'leri sorgulayabilir veya belirli bir alan içindeki tüm kapsamları bulabilir.
Bu işleme gereksinimleri, tam kapsamlı bir akış işleme altyapısı gerektirmeyeceği kadar basittir. Özellikle, işlem zaman pencereleri içinde akışlara, toplu veriye veya işleme katılamaz. Bu gereksinimlere bağlı olarak, Azure Işlevleri iletileri işlemeye uygun bir yerdir. Cosmos DB, çok yüksek yazma verimini desteklemek için de ölçeklendirebilir.
Performansı izleme
Bu senaryoda ilginç bir performans zorluğu sunulmaktadır. Cihaz başına veri hızı bilinmektedir, ancak cihaz sayısı dalgalanmaya başlayabilir. Bu iş senaryosunda, gecikme süresi özellikle sıkı değildir. Bir drone 'ın bildirilen konumunun yalnızca bir dakika içinde doğru olması gerekir. Bu şekilde, işlev uygulaması zaman içinde ortalama alım oranı ile devam etmelidir.
IoT Hub iletileri bir günlük akışında depolar. Gelen iletiler akışın kuyruğu 'na eklenir. Akışın bir okuyucusu — bu durumda, işlev uygulaması, akışın geçiş hızını denetler. Okuma ve yazma yollarının bu şekilde ayrılması çok verimli IoT Hub, ancak aynı zamanda yavaş bir okuyucunun arkasına dönebileceği anlamına gelir. Bu durumu algılamak için, geliştirme ekibi, ileti açıklamasını ölçmek üzere özel bir ölçüm ekledi. Bu ölçüm, bir iletinin IoT Hub ulaştığı ve işlevin işleme için ileti aldığı zaman arasındaki değişikliği kaydeder.
var ticksUTCNow = DateTimeOffset.UtcNow;
// Track whether messages are arriving at the function late.
DateTime? firstMsgEnqueuedTicksUtc = messages[0]?.EnqueuedTimeUtc;
if (firstMsgEnqueuedTicksUtc.HasValue)
{
CustomTelemetry.TrackMetric(
context,
"IoTHubMessagesReceivedFreshnessMsec",
(ticksUTCNow - firstMsgEnqueuedTicksUtc.Value).TotalMilliseconds);
}
TrackMetricyöntemi Application Insights bir özel ölçüm yazar. Azure Işlevi içinde kullanma hakkında daha fazla bilgi için TrackMetric bkz. TrackMetric.
İşlev, ileti hacimiyle devam ederse, bu ölçüm düşük kararlı bir durumda kalır. Bazı gecikme kaçınılmaz, bu nedenle değer hiçbir zaman sıfır olmayacaktır. Ancak işlev arkasında kalırsa, sıraya alınan zaman ve işleme süresi arasındaki Delta çalışmaya başlar.
Test 1: taban çizgisi
ilk yük testi bir sorun olduğunu gösterdi: işlev uygulaması, Cosmos DB Cosmos DB, yazma isteklerini azaltdığını belirten, sürekli olarak HTTP 429 hataları aldı.

yanıt olarak, takım, koleksiyon için ayrılan ru sayısını artırarak Cosmos DB ölçeklendi, ancak hatalar devam ediyor. bu, zarf arka arkaya hesaplanmasının, Cosmos DB yazma isteklerinin hacminde hiçbir sorun olmadığından emin olduğunu gösterdi.
Bu gün daha sonra, geliştiricilerden biri ekibe aşağıdaki e-postayı gönderdi:
ısınma yolu için Cosmos DB baktım. Anladığım bir şey var. bölüm anahtarı deliveryıd 'dir, ancak Cosmos DB için deliveryıd gönderiyoruz. Bir şey yok mu?
Bu, Clue idi. Bölüm ısı eşlemesine göz atın, tüm belgelerin aynı bölüme giriş olduğunu de kapatmış demektir.

Isı haritasında görmek istediğiniz şey tüm bölümler genelinde eşit bir dağıtımdır. Bu durumda, her belge aynı bölüme yazıldığı için, ru eklemek yardım etmedi. Sorun, koddaki bir hata olarak kapatıldı. Cosmos DB koleksiyonu bir bölüm anahtarına sahip olsa da, Azure işlevi belgeye bölüm anahtarını gerçekten dahil etmedi. Bölüm ısı haritası hakkında daha fazla bilgi için bkz. bölümler arasında üretilen iş dağıtımını belirleme.
Test 2: bölümlendirme sorununu çözme
takım bir kod düzeltmesini dağıttı ve testi yeniden çalıştırmışsa Cosmos DB azaltmayı durdurdu. Bir süre boyunca her şey iyi şekilde aranır. Ancak belirli bir yüklemede telemetri, işlevin gereken daha az belge yazdığının gösterdi. aşağıdaki grafikte, Cosmos DB yazılan belgelerden IoT Hub karşı alınan iletiler gösterilmektedir. Sarı satır, toplu iş başına alınan ileti sayısıdır ve yeşil, toplu işlem başına yazılan belge sayısıdır. Bunlar orantılı olmalıdır. Bunun yerine, toplu işlem başına veritabanı yazma işlemi sayısı 07:30 hakkında önemli ölçüde düşer.

Sonraki grafikte, bir iletinin bir cihazdan IoT Hub ulaştığında ve işlev uygulamasının bu iletiyi işlemesi arasındaki gecikme süresi gösterilir. Aynı noktada aynı noktada, en uygun noktaları önemli ölçüde, düzeylerin kapalı olduğunu ve reddetme süresini görebilirsiniz.

Değerin 5 dakikadan kısa bir süre boyunca üst düzeye düşme nedeni, işlev uygulamasının 5 dakikadan daha geç olan iletileri dışlamasıdır:
foreach (var message in messages)
{
// Drop stale messages,
if (message.EnqueuedTimeUtc < cutoffTime)
{
log.Info($"Dropping late message batch. Enqueued time = {message.EnqueuedTimeUtc}, Cutoff = {cutoffTime}");
droppedMessages++;
continue;
}
Bu, azlık ölçümü sıfıra geri düştüğünde grafiği grafik halinde görebilirsiniz. Bu sırada, işlevin iletileri oluşturduğundan veriler kayboldu.
Neler oluyor? bu belirli yük testi için, Cosmos DB koleksiyonu, bu nedenle, performans sorunu veritabanında değildi. Bunun yerine, sorun ileti işleme döngüsüyle vardı. Basitçe, işlev, gelen ileti hacminde tutmaya yetecek kadar hızlı bir şekilde belge yazmamıştır. Zaman içinde, daha fazla ve daha sonra geri döndü.
Test 3: paralel yazma
Bir iletiyi işlemek için geçen süre performans sorunu olursa, bir çözüm daha fazla iletiyi paralel olarak işlemelidir. Bu senaryoda:
- IoT Hub bölümlerinin sayısını artırın. Her bir IoT Hub bölümü tek seferde bir işlev örneğine atanır. bu nedenle, üretilen iş, Bölüm sayısıyla doğrusal bir şekilde ölçeklendirilmesine neden olur.
- Paralel hale getirmek işlevi, işlevin içinde yazar.
İkinci seçeneği araştırmak için, takım işlevi paralel yazmaları destekleyecek şekilde değiştirdi. işlevin orijinal sürümü Cosmos DB çıkış bağlamayıkullandı. iyileştirilmiş sürüm Cosmos DB istemcisini doğrudan çağırır ve görev. whenallkullanarak yazma işlemleri paralel olarak gerçekleştirir:
private async Task<(long documentsUpserted,
long droppedMessages,
long cosmosDbTotalMilliseconds)>
ProcessMessagesFromEventHub(
int taskCount,
int numberOfDocumentsToUpsertPerTask,
EventData[] messages,
TraceWriter log)
{
DateTimeOffset cutoffTime = DateTimeOffset.UtcNow.AddMinutes(-5);
var tasks = new List<Task>();
for (var i = 0; i < taskCount; i++)
{
var docsToUpsert = messages
.Skip(i * numberOfDocumentsToUpsertPerTask)
.Take(numberOfDocumentsToUpsertPerTask);
// client will attempt to create connections to the data
// nodes on Cosmos db's clusters on a range of port numbers
tasks.Add(UpsertDocuments(i, docsToUpsert, cutoffTime, log));
}
await Task.WhenAll(tasks);
return (this.UpsertedDocuments,
this.DroppedMessages,
this.CosmosDbTotalMilliseconds);
}
Yarış durumlarının yaklaşım ile mümkün olduğunu unutmayın. Aynı drone 'dan gelen iki iletinin aynı ileti toplu iş için gelmesi gerektiğini varsayalım. Bunları paralel yazarak, önceki ileti daha sonra gelen iletinin üzerine yazabilir. Bu senaryoda, uygulama zaman zaman bir iletiyi kaybediyor olabilir. drones, her 5 saniyede bir yeni konum verileri gönderiyor, bu nedenle Cosmos DB içindeki veriler sürekli olarak güncelleştirilir. Ancak, diğer senaryolarda iletileri tamamen sırayla işlemek önemli olabilir.
Bu kod değişikliğini dağıttıktan sonra, uygulama 32 bölümlü bir IoT Hub kullanarak 2500 istekten daha fazlasını alabilir.
İstemci tarafı değerlendirmesi
Genel istemci deneyimi sunucu tarafında ısrarlı paralelleştirme tarafından düşebilir. bir Cosmos DB kapsayıcısına ayrılan üretilen iş üretimini ortadan kaldırmaya yönelik gereken istemci tarafı işlem kaynaklarını önemli ölçüde azaltan Azure Cosmos DB toplu yürütücü kitaplığı 'nı (bu uygulamada gösterilmez) kullanmayı göz önünde bulundurun. Toplu içeri aktarma API 'sini kullanarak veri yazan tek bir iş parçacıklı uygulama, istemci makinenin CPU 'SU için performans elde edilirken, verileri paralel olarak yazan çok iş parçacıklı bir uygulamayla karşılaştırıldığında neredeyse on kat daha fazla yazma işi elde eder.
Özet
Bu senaryo için aşağıdaki performans sorunları tanımlanmıştır:
- Yazılan belgelerde eksik bölüm anahtarı değeri nedeniyle, etkin yazma bölümü.
- IoT Hub bölüm başına seri olarak belge yazma.
Bu sorunları tanılamak için, geliştirme ekibi aşağıdaki ölçümlere güvendi:
- Cosmos DB kısıtlanan istekler.
- Bölüm ısı haritası — bölüm başına en fazla RUs.
- Alınan iletiler ve oluşturulan belgeler.
- İleti bütünlüğü.
Sonraki adımlar
Performans önleme düzenlerini gözden geçirme