News Archyuk

.NET 6 अनुप्रयोगों में प्रदर्शन बाधाओं का निवारण करें

जब आप उनसे कम से कम उम्मीद करते हैं तो प्रदर्शन के मुद्दे कम हो सकते हैं। इससे आपके ग्राहकों के लिए नकारात्मक परिणाम हो सकते हैं। जैसे-जैसे उपयोगकर्ता आधार बढ़ता है, आपका ऐप पिछड़ सकता है क्योंकि यह मांग को पूरा करने में सक्षम नहीं होता है। सौभाग्य से, इन मुद्दों से समय पर निपटने के लिए उपकरण और तकनीकें उपलब्ध हैं।

हमने इस लेख को साझेदारी में बनाया है साइट24×7. साइटपॉइंट को संभव बनाने वाले भागीदारों का समर्थन करने के लिए धन्यवाद।

इस टेक में, मैं .NET 6 एप्लिकेशन में प्रदर्शन की बाधाओं का पता लगाऊंगा। फोकस एक प्रदर्शन मुद्दे पर होगा जिसे मैंने व्यक्तिगत रूप से उत्पादन में देखा है। मंशा यह है कि आप अपने स्थानीय देव परिवेश में समस्या को पुन: उत्पन्न करने और समस्या से निपटने में सक्षम हों।

से नमूना कोड डाउनलोड करने के लिए स्वतंत्र महसूस करें GitHub या साथ पालन करें। समाधान में दो एपीआई हैं, जिन्हें अकल्पनीय रूप से नामित किया गया है First.Api और Second.Api. मौसम डेटा प्राप्त करने के लिए पहला एपीआई दूसरे एपीआई में कॉल करता है। यह एक सामान्य उपयोग का मामला है, क्योंकि एपीआई अन्य एपीआई में कॉल कर सकते हैं, ताकि डेटा स्रोत अलग-अलग रहें और व्यक्तिगत रूप से स्केल कर सकें।

सबसे पहले, सुनिश्चित करें कि आपके पास है .NET 6 एसडीके आपकी मशीन पर स्थापित। फिर, टर्मिनल या कंसोल विंडो खोलें:

> dotnet new webapi --name First.Api --use-minimal-apis --no-https --no-openapi
> dotnet new webapi --name Second.Api --use-minimal-apis --no-https --no-openapi

उपरोक्त समाधान फ़ोल्डर में जा सकते हैं जैसे performance-bottleneck-net6. यह न्यूनतम एपीआई के साथ दो वेब प्रोजेक्ट बनाता है, कोई एचटीटीपीएस नहीं है, और कोई स्वैगर या ओपन एपीआई नहीं है। उपकरण फ़ोल्डर संरचना को मचान बनाता है, इसलिए यदि आपको इन दो नई परियोजनाओं को स्थापित करने में सहायता की आवश्यकता है तो कृपया नमूना कोड देखें।

समाधान फ़ाइल समाधान फ़ोल्डर में जा सकती है। यह आपको राइडर या विज़ुअल स्टूडियो जैसे आईडीई के माध्यम से संपूर्ण समाधान खोलने की अनुमति देता है:

dotnet new sln --name Performance.Bottleneck.Net6
dotnet sln add First.ApiFirst.Api.csproj
dotnet sln add Second.ApiSecond.Api.csproj

अगला, प्रत्येक वेब प्रोजेक्ट के लिए पोर्ट नंबर सेट करना सुनिश्चित करें। नमूना कोड में, मैंने उन्हें पहले एपीआई के लिए 5060 और दूसरे के लिए 5176 पर सेट किया है। विशिष्ट संख्या कोई मायने नहीं रखती है, लेकिन मैं इनका उपयोग पूरे नमूना कोड में एपीआई को संदर्भित करने के लिए करूंगा। इसलिए, सुनिश्चित करें कि आप या तो अपने पोर्ट नंबर बदल दें या जो मचान उत्पन्न करता है उसे बनाए रखें और लगातार बने रहें।

अपमानजनक आवेदन

को खोलो Program.cs दूसरे एपीआई में फाइल करें और उस कोड को रखें जो मौसम डेटा के साथ प्रतिक्रिया करता है:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var summaries = new[]
{
 "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherForecast", async () =>
{
 await Task.Delay(10);
 return Enumerable
   .Range(0, 1000)
   .Select(index =>
     new WeatherForecast
     (
       DateTime.Now.AddDays(index),
       Random.Shared.Next(-20, 55),
       summaries[Random.Shared.Next(summaries.Length)]
     )
   )
   .ToArray()[..5];
});

app.Run();

public record WeatherForecast(
 DateTime Date,
 int TemperatureC,
 string? Summary)
{
 public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

.NET 6 में न्यूनतम एपीआई सुविधा कोड को छोटा और संक्षिप्त रखने में मदद करती है। यह एक हजार रिकॉर्ड के माध्यम से लूप करेगा, और यह async डेटा प्रोसेसिंग को सिम्युलेट करने के लिए एक कार्य विलंब करता है। एक वास्तविक परियोजना में, यह कोड एक वितरित कैश, या डेटाबेस में कॉल कर सकता है, जो कि आईओ-बाउंड ऑपरेशन है।

अब, पर जाएँ Program.cs पहले एपीआई में फ़ाइल करें और इस मौसम डेटा का उपयोग करने वाले कोड को लिखें। आप बस इसे कॉपी-पेस्ट कर सकते हैं और मचान जो कुछ भी उत्पन्न करता है उसे बदल सकते हैं:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton(_ => new HttpClient(
 new SocketsHttpHandler
 {
   PooledConnectionLifetime = TimeSpan.FromMinutes(5)
 })
{
 BaseAddress = new Uri("")
});

var app = builder.Build();

app.MapGet("https://news.google.com/", async (HttpClient client) =>
{
 var result = new List<List<WeatherForecast>?>();

 for (var i = 0; i < 100; i++)
 {
   result.Add(
     await client.GetFromJsonAsync<List<WeatherForecast>>(
       "/weatherForecast"));
 }

 return result[Random.Shared.Next(0, 100)];
});

app.Run();

public record WeatherForecast(
 DateTime Date,
 int TemperatureC,
 string? Summary)
{
 public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

HttpClient सिंगलटन के रूप में इंजेक्ट किया जाता है, क्योंकि यह क्लाइंट को स्केलेबल बनाता है। .NET में, एक नया क्लाइंट अंतर्निहित ऑपरेटिंग सिस्टम में सॉकेट बनाता है, इसलिए कक्षा का पुन: उपयोग करके उन कनेक्शनों का पुन: उपयोग करना एक अच्छी तकनीक है। यहां, HTTP क्लाइंट एक कनेक्शन पूल लाइफटाइम सेट करता है। यह क्लाइंट को आवश्यकतानुसार लंबे समय तक सॉकेट पर लटकाए रखने की अनुमति देता है।

एक आधार पता केवल क्लाइंट को बताता है कि कहां जाना है, इसलिए सुनिश्चित करें कि यह दूसरे एपीआई में सही पोर्ट नंबर सेट की ओर इशारा करता है।

जब कोई अनुरोध आता है, तो कोड सौ बार लूप करता है, फिर दूसरे एपीआई में कॉल करता है। यह, उदाहरण के लिए, अन्य API में कॉल करने के लिए आवश्यक कई रिकॉर्ड अनुकरण करने के लिए है। पुनरावृत्तियों को हार्डकोड किया गया है, लेकिन एक वास्तविक परियोजना में यह उपयोगकर्ताओं की एक सूची हो सकती है, जो व्यापार बढ़ने पर असीमित रूप से बढ़ सकता है।

अब, अपना ध्यान लूपिंग पर केंद्रित करें, क्योंकि इसका प्रदर्शन सिद्धांत में निहितार्थ है। एल्गोरिथम विश्लेषण में, एक लूप में बिग-ओ रैखिक जटिलता या ओ (एन) है। लेकिन, दूसरा एपीआई भी लूप करता है, जो एल्गोरिथ्म को द्विघात या O(n^2) जटिलता में बदल देता है। साथ ही, लूपिंग बूट करने के लिए आईओ सीमा से गुज़रता है, जो प्रदर्शन को खराब करता है।

इसका गुणात्मक प्रभाव है, क्योंकि पहले एपीआई में प्रत्येक पुनरावृत्ति के लिए, दूसरा एपीआई एक हजार बार लूप करता है। 100 * 1000 पुनरावृत्तियाँ हैं। याद रखें, ये सूचियाँ अनबाउंड हैं, जिसका अर्थ है कि डेटासेट बढ़ने पर प्रदर्शन तेजी से घटेगा।

जब क्रोधित ग्राहक बेहतर उपयोगकर्ता अनुभव की मांग करते हुए कॉल सेंटर को स्पैम कर रहे हों, तो इन उपकरणों का उपयोग यह पता लगाने के लिए करें कि क्या हो रहा है।

कर्ल और एनबॉम्बर

पहला टूल किस एपीआई पर ध्यान केंद्रित करने में मदद करेगा। कोड का अनुकूलन करते समय, सब कुछ अंतहीन रूप से अनुकूलित करना संभव है, इसलिए समयपूर्व अनुकूलन से बचें। लक्ष्य “पर्याप्त अच्छा” होने के लिए प्रदर्शन प्राप्त करना है, और यह व्यक्तिपरक होता है और व्यावसायिक मांगों से प्रेरित होता है।

सबसे पहले, प्रत्येक एपीआई में अलग-अलग कर्ल का उपयोग करके कॉल करें, उदाहरण के लिए, विलंबता के लिए महसूस करने के लिए:

> curl -i -o /dev/null -s -w %{time_total} 
> curl -i -o /dev/null -s -w %{time_total} 

पोर्ट नंबर 5060 पहले एपीआई का है, और 5176 दूसरे का है। सत्यापित करें कि क्या ये आपकी मशीन पर सही पोर्ट हैं।

दूसरा एपीआई एक सेकंड के अंशों में प्रतिक्रिया करता है, जो काफी अच्छा है और संभवतः अपराधी नहीं है। लेकिन पहले एपीआई को प्रतिक्रिया देने में लगभग दो सेकंड लगते हैं। यह अस्वीकार्य है, क्योंकि वेब सर्वर उन अनुरोधों को टाइमआउट कर सकते हैं जिनमें इतना समय लगता है। साथ ही, ग्राहक के दृष्टिकोण से दो-सेकंड की विलंबता बहुत धीमी है, क्योंकि यह एक विघटनकारी विलंब है।

अगला, NBomber जैसा टूल समस्याग्रस्त API को बेंचमार्क करने में मदद करेगा।

कंसोल पर वापस जाएं और रूट फ़ोल्डर के अंदर एक टेस्ट प्रोजेक्ट बनाएं:

dotnet new console -n NBomber.Tests
cd NBomber.Tests
dotnet add package NBomber
dotnet add package NBomber.Http
cd ..
dotnet sln add NBomber.TestsNBomber.Tests.csproj

में Program.cs फ़ाइल, बेंचमार्क लिखें:

using NBomber.Contracts;
using NBomber.CSharp;
using NBomber.Plugins.Http.CSharp;

var step = Step.Create(
 "fetch_first_api",
 clientFactory: HttpClientFactory.Create(),
 execute: async context =>
 {
   var request = Http
     .CreateRequest("GET", "/")
     .WithHeader("Accept", "application/json");
   var response = await Http.Send(request, context);

   return response.StatusCode == 200
     ? Response.Ok(
       statusCode: response.StatusCode,
       sizeBytes: response.SizeBytes)
     : Response.Fail();
 });

var scenario = ScenarioBuilder
 .CreateScenario("first_http", step)
 .WithWarmUpDuration(TimeSpan.FromSeconds(5))
 .WithLoadSimulations(
   Simulation.InjectPerSec(rate: 1, during: TimeSpan.FromSeconds(5)),
   Simulation.InjectPerSec(rate: 2, during: TimeSpan.FromSeconds(10)),
   Simulation.InjectPerSec(rate: 3, during: TimeSpan.FromSeconds(15))
 );

NBomberRunner
.RegisterScenarios(scenario)
.Run();

NBomber केवल एक अनुरोध प्रति सेकंड की दर से API को स्पैम करता है। फिर, अंतराल पर, अगले दस सेकंड के लिए प्रति सेकंड दो बार। अंत में, अगले 15 सेकंड के लिए प्रति सेकंड तीन बार। यह स्थानीय देव मशीन को बहुत अधिक अनुरोधों के साथ ओवरलोडिंग से बचाता है। NBomber नेटवर्क सॉकेट्स का भी उपयोग करता है, इसलिए सावधानी से चलें जब लक्ष्य API और बेंचमार्क टूल दोनों एक ही मशीन पर चलते हैं।

परीक्षण कदम प्रतिक्रिया कोड को ट्रैक करता है और इसे रिटर्न वैल्यू में रखता है। यह एपीआई विफलताओं का ट्रैक रखता है। .NET में, जब Kestrel सर्वर को बहुत अधिक अनुरोध प्राप्त होते हैं, तो यह विफलता प्रतिक्रिया वाले लोगों को अस्वीकार कर देता है।

अब, परिणामों का निरीक्षण करें और लेटेंसी, समवर्ती अनुरोध और थ्रूपुट की जांच करें।

P95 विलंबता 1.5 सेकंड दिखाती है, जो कि अधिकांश ग्राहक अनुभव करेंगे। थ्रूपुट कम रहता है, क्योंकि टूल को केवल तीन अनुरोध प्रति सेकंड तक जाने के लिए कैलिब्रेट किया गया था। एक स्थानीय देव मशीन में, समवर्तीता का पता लगाना कठिन है, क्योंकि बेंचमार्क टूल चलाने वाले समान संसाधन भी अनुरोधों को पूरा करने के लिए आवश्यक हैं।

डॉटट्रेस विश्लेषण

अगला, एक उपकरण चुनें जो एल्गोरिथम विश्लेषण कर सकता है जैसे डॉटट्रेस। यह आगे अलग करने में मदद करेगा जहां प्रदर्शन समस्या हो सकती है।

एक विश्लेषण करने के लिए, डॉटट्रेस चलाएं और एनबॉम्बर द्वारा एपीआई को जितना संभव हो उतना मुश्किल से स्पैम करने के बाद एक स्नैपशॉट लें। लक्ष्य यह पहचानने के लिए भारी भार का अनुकरण करना है कि धीमापन कहां से आ रहा है। पहले से स्थापित मानक काफी अच्छे हैं इसलिए सुनिश्चित करें कि आप डॉटट्रेस को एनबॉम्बर के साथ चला रहे हैं।

डॉटट्रेस विश्लेषण

इस विश्लेषण के आधार पर, लगभग 85% समय पर खर्च किया जाता है GetFromJsonAsync बुलाना। टूल में इधर-उधर देखने से पता चलता है कि यह HTTP क्लाइंट से आ रहा है। यह प्रदर्शन सिद्धांत से संबंधित है, क्योंकि यह दिखाता है कि O(n^2) जटिलता के साथ async लूपिंग समस्या हो सकती है।

स्थानीय रूप से चलने वाला एक बेंचमार्क टूल अड़चनों की पहचान करने में मदद करेगा। अगला कदम एक निगरानी उपकरण का उपयोग करना है जो लाइव उत्पादन वातावरण में अनुरोधों को ट्रैक कर सकता है।

प्रदर्शन जांच सभी जानकारी एकत्र करने के बारे में हैं, और वे इस बात की जांच करते हैं कि प्रत्येक उपकरण कम से कम एक सुसंगत कहानी कह रहा है।

साइट24×7 निगरानी

एक उपकरण जैसा साइट24×7 प्रदर्शन संबंधी समस्याओं से निपटने में मदद कर सकता है।

इस एप्लिकेशन के लिए, आप दो API में P95 लेटेंसी पर ध्यान केंद्रित करना चाहते हैं। यह तरंग प्रभाव है, क्योंकि एपीआई एक वितरित वास्तुकला में परस्पर जुड़ी सेवाओं की एक श्रृंखला का हिस्सा हैं। जब एक एपीआई में प्रदर्शन की समस्या होने लगती है, तो अन्य एपीआई डाउनस्ट्रीम में भी समस्या आ सकती है।

स्केलेबिलिटी एक और महत्वपूर्ण कारक है। जैसे-जैसे यूजर बेस बढ़ता है, ऐप पिछड़ना शुरू कर सकता है। सामान्य व्यवहार को ट्रैक करना और भविष्यवाणी करना कि समय के साथ ऐप कैसे बढ़ता है, मदद करता है। इस ऐप पर पाया गया नेस्टेड एसिंक्स लूप N संख्या के उपयोगकर्ताओं के लिए अच्छा काम कर सकता है, लेकिन संख्या अनबाउंड होने के कारण स्केल नहीं हो सकता है।

अंत में, जैसा कि आप अनुकूलन और सुधार लागू करते हैं, यह संस्करण निर्भरताओं को ट्रैक करने की कुंजी है। प्रत्येक पुनरावृत्ति के साथ, आपको यह जानने में सक्षम होना चाहिए कि प्रदर्शन के लिए कौन सा संस्करण बेहतर या खराब है।

एक उचित निगरानी उपकरण आवश्यक है, क्योंकि स्थानीय विकास परिवेश में समस्याओं का पता लगाना हमेशा आसान नहीं होता है। स्थानीय रूप से बनाई गई धारणाएँ उत्पादन में मान्य नहीं हो सकती हैं, क्योंकि आपके ग्राहकों की राय अलग हो सकती है। Site24x7 का अपना 30 दिन का निःशुल्क परीक्षण शुरू करें.

एक अधिक प्रदर्शनकारी समाधान

अब तक उपकरणों के शस्त्रागार के साथ, यह बेहतर दृष्टिकोण का पता लगाने का समय है।

CURL ने कहा कि पहला API वह है जिसमें प्रदर्शन संबंधी समस्याएं हैं। इसका मतलब है कि दूसरे एपीआई में किए गए कोई भी सुधार नगण्य हैं। भले ही यहां एक तरंग प्रभाव है, दूसरी एपीआई से कुछ मिलीसेकंड शेविंग करने से कोई फर्क नहीं पड़ता है।

NBomber ने इस कहानी की पुष्टि की कि P95s पहले API में लगभग दो सेकंड में थे। फिर, डॉटट्रेस ने एसिंक्स लूप को अलग कर दिया, क्योंकि यह वह जगह है जहां एल्गोरिथ्म ने अपना अधिकांश समय बिताया। साइट24×7 जैसा एक निगरानी उपकरण P95 विलंबता, समय के साथ मापनीयता और संस्करण दिखाकर सहायक जानकारी प्रदान करेगा। संभवतः, नेस्टेड लूप पेश करने वाले विशिष्ट संस्करण में नुकीली विलंबताएँ होंगी।

प्रदर्शन सिद्धांत के अनुसार, द्विघात जटिलता एक बड़ी चिंता है, क्योंकि प्रदर्शन तेजी से घटता है। लूप के अंदर पुनरावृत्तियों की संख्या को कम करके जटिलता को समाप्त करना एक अच्छी तकनीक है।

.NET में एक सीमा यह है कि हर बार जब आप एक प्रतीक्षा देखते हैं, तो लॉजिक ब्लॉक हो जाता है और एक समय में केवल एक ही अनुरोध भेजता है। यह पुनरावृत्ति को रोकता है और प्रतिक्रिया देने के लिए दूसरी एपीआई की प्रतीक्षा करता है। प्रदर्शन के लिए यह दुखद खबर है।

एक ही समय में सभी HTTP अनुरोध भेजकर लूप को क्रश करने का एक सरल तरीका है:

app.MapGet("https://news.google.com/", async (HttpClient client) =>
 (await Task.WhenAll( 
   Enumerable
     .Range(0, 100)
     .Select(_ =>
       client.GetFromJsonAsync<List<WeatherForecast>>( 
         "/weatherForecast")
     )
   )
 )
 .ToArray()[Random.Shared.Next(0, 100)]);

यह लूप के अंदर वेट को न्यूक करेगा और केवल एक बार ब्लॉक करेगा। Task.WhenAll सब कुछ समानांतर में भेजता है, जो लूप को स्मैश करता है।

यह दृष्टिकोण काम कर सकता है, लेकिन यह दूसरे एपीआई को एक साथ कई अनुरोधों के साथ स्पैम करने का जोखिम चलाता है। वेब सर्वर अनुरोधों को अस्वीकार कर सकता है, क्योंकि उसे लगता है कि यह एक DoS हमला हो सकता है। एक समय में केवल कुछ भेजकर पुनरावृत्तियों को कम करने के लिए एक अधिक स्थायी दृष्टिकोण है:

var sem = new SemaphoreSlim(10); 

app.MapGet("https://news.google.com/", async (HttpClient client) =>
 (await Task.WhenAll(
   Enumerable
     .Range(0, 100)
     .Select(async _ =>
     {
       try
       {
         await sem.WaitAsync(); 
         return await client.GetFromJsonAsync<List<WeatherForecast>>(
           "/weatherForecast");
       }
       finally
       {
         sem.Release();
       }
     })
   )
 )
 .ToArray()[Random.Shared.Next(0, 100)]);

यह एक क्लब में बाउंसर की तरह काम करता है। अधिकतम क्षमता दस है। जैसे ही अनुरोध पूल में प्रवेश करता है, एक समय में केवल दस ही प्रवेश कर सकते हैं। यह समवर्ती अनुरोधों की भी अनुमति देता है, इसलिए यदि एक अनुरोध पूल से बाहर निकलता है, तो दूसरा तुरंत दस अनुरोधों पर प्रतीक्षा किए बिना प्रवेश कर सकता है।

यह एल्गोरिथम जटिलता को दस के कारक से कम करता है और सभी पागल लूपिंग से दबाव को राहत देता है।

इस कोड के साथ, NBomber चलाएं और परिणाम जांचें।

एक अधिक कुशल समाधान

P95 विलंबता अब एक तिहाई है जो वे हुआ करते थे। एक सेकंड से अधिक समय लेने वाली किसी भी प्रतिक्रिया की तुलना में आधा सेकंड की प्रतिक्रिया कहीं अधिक उचित है। बेशक, आप इसे जारी रख सकते हैं और इसे और अनुकूलित कर सकते हैं, लेकिन मुझे लगता है कि आपके ग्राहक इससे काफी प्रसन्न होंगे।

निष्कर्ष

प्रदर्शन अनुकूलन एक कभी न खत्म होने वाली कहानी है। जैसे-जैसे व्यवसाय बढ़ता है, कोड में एक बार की गई धारणा समय के साथ अमान्य हो सकती है। इसलिए, आपको प्रदर्शन की समस्याओं को दूर करने में मदद करने के लिए ऐप का विश्लेषण करने, बेंचमार्क बनाने और लगातार निगरानी करने के लिए टूल की आवश्यकता होती है।

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Most Popular

Get The Latest Updates

Subscribe To Our Weekly Newsletter

No spam, notifications only about new products, updates.

Categories

On Key

Related Posts

COVID प्रतिबंध हटने के बाद चीन में हॉलिडे ट्रिप्स में उछाल

बीजिंग — राज्य के मीडिया ने शनिवार को बताया कि अधिकारियों द्वारा COVID-19 यात्रा पर अंकुश लगाने के बाद चीन के अंदर चंद्र नव वर्ष

सिल्जे (37) को कोरोना का टीका लगने के बाद निकलवाना पड़ा गर्भाशय :- मैंने अपने जीवन का एक हिस्सा खो दिया है – एनआरके नोर्डलैंड

– सबसे बुरा तो यह था कि मुझे लगा कि खून बहने से मेरी मौत हो जाएगी, सिल्जे एनेट ब्रा कहती हैं। एनआरके के बारे

ट्रेनिंग के दौरान भी स्टाइलिश हैं सरका काटा (फोटो के साथ)

अन्य बातों के अलावा, काटा प्रशिक्षण के दौरान स्टाइलिश रहने का भी ध्यान रखता है, जिसके अपने फायदे भी हैं। एक प्रशिक्षण सत्र को उचित

इन 4 राशियों के लिए खुला है फरवरी का राज, LUBER खाते की शेष राशि तक धन और भाग्य साथ-साथ आते हैं

बेरीताजोवो.कॉम – दिखाया गया गुप्त फ़रवरी खोलना चौड़ा 4 के लिए राशि यह, कैसे और भी आइए साथ में जब तक संतुलन हेतु लुबेर फिर