Milyonlarca kullanıcıyı, B2C'de kullanıcıları oluşturmak için MS Graph API'sını kullanarak şirket içi AD'den Azure AD B2C'ye geçiriyorum. Bu taşımayı gerçekleştirmek için bir .Net Core 3.1 konsol uygulaması yazdım. İşleri hızlandırmak için Grafik API'sına eşzamanlı çağrılar yapıyorum. Bu harika çalışıyor - bir çeşit.
Geliştirme sırasında Visual Studio 2019'dan çalışırken kabul edilebilir bir performans yaşadım, ancak test için Powershell 7'deki komut satırından çalıştırıyorum. Powershell'den HttpClient'e eşzamanlı çağrıların performansı çok kötü. Powershell'den çalıştırırken HttpClient'in izin verdiği eşzamanlı çağrı sayısında bir sınır var gibi görünüyor, bu nedenle 40 ila 50 istekden daha büyük eşzamanlı gruplar halinde çağrılar birikmeye başlıyor. Geri kalanını engellerken 40 ila 50 eşzamanlı istek çalıştırıyor gibi görünüyor.
Zaman uyumsuz programlama konusunda yardım aramıyorum. Visual Studio çalışma zamanı davranışı ve Powershell komut satırı çalışma zamanı davranışı arasındaki farkı vurmanın bir yolunu arıyorum. Visual Studio'nun yeşil ok düğmesinden serbest bırakma modunda çalıştırmak beklendiği gibi davranır. Komut satırından çalıştırma yapmaz.
Bir görev listesini zaman uyumsuz çağrılarla dolduruyorum ve sonra Task.WhenAll (görevler) 'i bekliyorum. Her çağrı 300 ila 400 milisaniye sürer. Visual Studio'dan çalıştırırken beklendiği gibi çalışır. Eşzamanlı olarak 1000 çağrı yaparım ve her biri beklenen süre içinde tamamlanır. Tüm görev bloğu, en uzun bireysel çağrıdan sadece birkaç milisaniye daha uzun sürer.
Powershell komut satırından aynı derlemeyi çalıştırdığımda davranış değişir. İlk 40 ila 50 çağrı beklenen 300 ila 400 milisaniye sürer, ancak bireysel çağrı sürelerinin her biri 20 saniyeye kadar uzar. Ben aramalar seri hale düşünüyorum, bu yüzden diğerleri beklerken bir anda sadece 40 ila 50 yürütülmektedir.
Saatlerce süren deneme yanılma işleminden sonra HttpClient'e daraltabiliyorum. Sorunu izole etmek için HttpClient.SendAsync çağrılarını Task.Delay (300) yapan bir yöntemle alay ettim ve bir sahte sonuç döndürür. Bu durumda, konsoldan çalışan Visual Studio'dan çalışanla aynı şekilde davranır.
IHttpClientFactory kullanıyorum ve hatta ServicePointManager bağlantı sınırını ayarlamaya çalıştım.
İşte kayıt kodum.
public static IServiceCollection RegisterHttpClient(this IServiceCollection services, int batchSize)
{
ServicePointManager.DefaultConnectionLimit = batchSize;
ServicePointManager.MaxServicePoints = batchSize;
ServicePointManager.SetTcpKeepAlive(true, 1000, 5000);
services.AddHttpClient(MSGraphRequestManager.HttpClientName, c =>
{
c.Timeout = TimeSpan.FromSeconds(360);
c.DefaultRequestHeaders.Add("User-Agent", "xxxxxxxxxxxx");
})
.ConfigurePrimaryHttpMessageHandler(() => new DefaultHttpClientHandler(batchSize));
return services;
}
İşte DefaultHttpClientHandler.
internal class DefaultHttpClientHandler : HttpClientHandler
{
public DefaultHttpClientHandler(int maxConnections)
{
this.MaxConnectionsPerServer = maxConnections;
this.UseProxy = false;
this.AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate;
}
}
İşte görevleri ayarlayan kod.
var timer = Stopwatch.StartNew();
var tasks = new Task<(UpsertUserResult, TimeSpan)>[users.Length];
for (var i = 0; i < users.Length; ++i)
{
tasks[i] = this.CreateUserAsync(users[i]);
}
var results = await Task.WhenAll(tasks);
timer.Stop();
İşte ben HttpClient alay ettim.
var httpClient = this.httpClientFactory.CreateClient(HttpClientName);
#if use_http
using var response = await httpClient.SendAsync(request);
#else
await Task.Delay(300);
var graphUser = new User { Id = "mockid" };
using var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(JsonConvert.SerializeObject(graphUser)) };
#endif
var responseContent = await response.Content.ReadAsStringAsync();
500 eşzamanlı istek kullanılarak GraphAPI aracılığıyla oluşturulan 10 bin B2C kullanıcısı için metrikler. TCP bağlantıları oluşturulduğu için ilk 500 istek normalden daha uzun.
İşte konsol çalıştırma metriklerine bir bağlantı .
İşte Visual Studio çalıştırma metriklerine bir bağlantı .
VS çalışma metriklerindeki blok süreleri, bu yayında söylediğimden farklıdır, çünkü tüm senkronize dosya erişimini, test kodları için mümkün olduğunca sorunlu kodu yalıtmak amacıyla sürecin sonuna taşıdım.
Proje .Net Core 3.1 kullanılarak derlenmiştir. Visual Studio 2019 16.4.5 kullanıyorum.