اگر سی شارپ زبان مورد استفاده شما نیست، نگران نباشید. فقط به اصول اولیه این تکنیک تست نیاز دارید. اگر می خواهید اصول اولیه تکنیک تست بار را یاد بگیرید، می توانم خواندن این مطلب را به شما توصیه کنم.
جهت جلوگیری از خستگی خواننده کل مطلب را در دو بخش تقسیم میکنم:
1- بخش اول شامل توضیح اصول تست و مشاهده یک نمونه(شما در حال خواندن این بخش هستید)
2- بخش دوم شامل آموزش تست نویسی واقعی و بررسی عمیق تر نتایج تست بار
تست بار ، تعاملات n کاربر با سیستم را شبیه سازی می کند و اطلاعاتی از قبیل زمان پاسخ دهی به کاربر را بر اساس معیارهایی مانند استفاده از RAM و CPU جمع آوری میکند. تست بار به شما کمک میکند تا مشکلات عملکردی را پیدا کنید که ممکن است فقط برای بیش از 1000 کاربر رخ دهد، و پس از آن باعث مشود مشکلات بزرگی برای عملکرد سرویس شما ایجاد کند. این تجربه برای ما یک کوئری نا کارآمد بود که باعث می شد به طور مکرر نیاز به راه اندازی مجدد سرویس و مقیاس بندی عمودی و افقی(سخت افزاری و نرم افزاری) شود.
موضوع تست بار چیزی فراتر از این است که بپرسیم آیا یک سرور می تواند اتصال همزمان n کاربر را مدیریت کند؟ بعنوان مثال ممکن است بگویید در عمل این اتفاق هیچ وقت برای سرویس من اتفاق نخواهد افتاد و نباید به آن اهمیت بدهیم!
ممکن است این اتفاق زمانی که مورد حمله DDos قرار میگیریم مورد توجه قرار گیرد، که البته در این مطلب راجع به آن صحبت نمی کنیم. علاوه بر این ، ما باید رفتار واقعی کاربران با سیستم را شبیه سازی کنیم و سپس اطلاعات جمع آوری شده توسط تست بار را جهت محاسبه زمان پاسخ دهی واقعی سرویس خودمان بدست بیاوریم.این کار برای پیدا کردن درخواست هایی که باعث ایجاد مشکل در سرویس دهی شما می شوند و بررسی آنها توسط ابزار های نظارت بر عملکرد سرویس شما بسیار مفید است.
ابزار NBomber عملکرد بسیار خوبی در شبیه سازی درخواست ها برای پیدا کردن مشکلات عملکردی سرویس شما دارد.
یاکوب نیلسن(راجع به ایشان بیشتر بخوانید) سه محدودیت زمان پاسخ را برای برنامه ها تعریف کرده است:
تست بار ابزاری است که قابلیت آزمایش تست عملکرد سیستم در شرایط واقعی، بدون داشتن کاربران واقعی را به ما می دهد.
هنگامی که در یک استارت آپ هستید و در حال حاضر مانند من در حال آماده سازی برنامه خود برای انتشار هستید، آیا می توانید مطمعن باشید که این برنامه می تواند تعداد کاربران را که می خواهید داشته باشید مدیریت کند؟
برای من همیشه یک نگرانی بزرگ وجود داشت که آیا برنامه می تواند به 10 نفر سرویس دهی کند؟ برای 1000 نفر چطور؟ یا حتی بیشتر؟ آیا میتواندی چنین آزمایشی را چندین بار در روز انجام دهید؟ من اینطور فکر نمی کنم. شما هرگز نمی توانید این کار را انجام دهید چون هیچ راهی برای آزمایش دستی وجود ندارد. اینجاست که تست بار وارد عمل می شود. با تست بار می توانید برنامه خود را تست استرس کنید و با اطمینان بگویید که برای صدها کاربر کار خواهد کرد. این موضوع نه تنها قبل از راه اندازی یک سرویس مهم است، بلکه قبل از راه اندازی یک ویژگی جدید نیز اهمیت دارد. زیرا ممکن است عملکرد برنامه شما را تحت تاثیر قرارداده و خراب کند بطوری که قبل از بروزرسانی نسخه جدید متوجه آن نخواهید شد.
در بالا میتوانید کاربری را مشاهده کنید که از برنامهای که بدون آزمایش بارگذاری توسعه یافته است استفاده میکند. شما چنین کاربری را نمی خواهید! کاربرانی که قبلاً خوشحال بودند، اکنون می توانند ناراضی باشند، برنامه شما را ترک کنند یا ممکن است اشتراک را لغو کنند. مطمئناً امتیازات اعتماد کاربران خود را از دست خواهید داد. بنابراین پیشنهاد میکنم لطفاً برخی از تست های بار را نیز در CI خود ادغام کنید.
بهتر است بگویم NBomber یک ابزار با کاربری راحت برای آزمایش عملکرد برنامه شماست که علاوه بر نوشتن و اجرا کردن سریع تست ها داده های مفیدی را در اختیار شما می گذارد تا با خیال راحت بصورت واقعی سرویس خود را تست کنید.
بزرگترین مزیت شبیه سازی تست بار این است که شما فقط 100 درخواست را بصورت همزان اجرا نمی کنید بلکه رفتار واقعی کاربران را با توجه به اطلاعات ارائه شده توسط NBomber شبیه سازی می کنید.
از آنجایی که خود تست ها به سادگی فراخوانی API های شماست، می توان گفت این یک تست از نوع جعبه سیاه است. این بدان معناست که با NBomber می توانید هر پروژه ای را بدون در نظر گرفتن زبان برنامه نویسی آن آزمایش کنید.
ابتدا یک پروژه Console Application ایجاد میکنیم.
dotnet new console -n [project_name] -lang ["F#" or "C#"]
dotnet new console -n NBomberTest -lang "F#"
cd NBomberTest
اضافه کردن پکیج NBomber
dotnet add package NBomber
مطمعن شوید که بسته Http را برای ارسال درخواست های http نصب کنید
dotnet add package NBomber.http
در مرحله بعد بیایید یک مثال اجرایی را از تست وب سایت NBomber ببینیم
using System; using NBomber; using NBomber.Contracts; using NBomber.CSharp; using NBomber.Plugins.Http.CSharp; using NBomber.Plugins.Network.Ping;namespace NBomberTest { class Program { static void Main(string[] args) { var step = Step.Create("fetch_html_page", clientFactory: HttpClientFactory.Create(), execute: context => { var request = Http.CreateRequest("GET", "https://nbomber.com") .WithHeader("Accept", "text/html"); return Http.Send(request, context); }); var scenario = ScenarioBuilder .CreateScenario("simple_http", step) .WithWarmUpDuration(TimeSpan.FromSeconds(5)) .WithLoadSimulations( Simulation.InjectPerSec(rate: 100, during: TimeSpan.FromSeconds(30)) ); // creates ping plugin that brings additional reporting data var pingPluginConfig = PingPluginConfig.CreateDefault(new[] { "nbomber.com" }); var pingPlugin = new PingPlugin(pingPluginConfig); NBomberRunner .RegisterScenarios(scenario) .WithWorkerPlugins(pingPlugin) .Run(); } } }
کد بالا را در فایل Program.cs پروژه که ایجاد کردید کپی کنید.
مطمعن شوید که از C# نسخه 9 به بعد استفاده میکنید. اگر از نسخه قدیمی تر استفاده می کنید می توانید نسخه C# را در فایل .csproj پروژه خود به روز کنید.برای این کار تگ زیر را در فایل .csproj داخل تگ <PropertyGroup> کپی کنید یا در صورت وجود مقدار آن را تغییر دهید.
<LangVersion>10.0</LangVersion>
حالا پروژه را اجرا کنید تا نتیجه بمباران را مشاهده کنید. :)
نتیجه ای که در Console خواهید دید چیزی شبیه این می باشد:
12:24:20 [INF] NBomber '2.1.5' Started a new session: '2022-03-23_11.24.44_session_787459f0'. 12:24:21 [INF] NBomber started as single node. 12:24:21 [INF] Plugins: no plugins were loaded. 12:24:21 [INF] Reporting sinks: no reporting sinks were loaded. 12:24:21 [INF] Starting init... 12:24:21 [INF] Target scenarios: 'simple_http'. 12:24:21 [INF] Init finished. 12:24:21 [INF] Starting warm up... simple_http ---------------------------------------- 100% 00:00:30 load: keep_constant, copies: 112:24:53 [INF] Starting bombing... simple_http ---------------------------------------- 100% 00:01:01 load: keep_constant, copies: 112:25:54 [INF] Stopping scenarios... 12:25:54 [INF] Calculating final statistics...────────────────────────────────────────────────────── test info ───────────────────────────────────────────────────────test suite: 'nbomber_default_test_suite_name' test name: 'nbomber_default_test_name'──────────────────────────────────────────────────── scenario stats ────────────────────────────────────────────────────scenario: 'simple_http' duration: '00:01:00', ok count: 662, fail count: 0, all data: 0 MB load simulation: 'keep_constant', copies: 1, during: '00:01:00' ┌────────────────────┬────────────────────────────────────────────────────────┐ │ step │ ok stats │ ├────────────────────┼────────────────────────────────────────────────────────┤ │ name │ fetch_html_page │ │ request count │ all = 662, ok = 662, RPS = 11 │ │ latency │ min = 59,66, mean = 90,47, max = 367,5, StdDev = 32,04 │ │ latency percentile │ 50% = 79,61, 75% = 92,48, 95% = 158,98, 99% = 209,15 │ └────────────────────┴────────────────────────────────────────────────────────┘──────────────────────────────────────────────────────── hints ─────────────────────────────────────────────────────────
hint for Scenario 'simple_http': Step 'fetch_html_page' in scenario 'simple_http' didn't track status code. In order to track status code, you should use Response.Ok(statusCode: value)hint for Scenario 'simple_http': Step 'fetch_html_page' in scenario 'simple_http' didn't track data transfer. In order to track data transfer, you should use Response.Ok(sizeInBytes: value)12:25:55 [INF] Reports saved in folder:...
بنا بر این NBomber سرویس را آزمایش کرد و اطلاعاتی در مورد آن جمع آوری کرد.
برای درک خروجی تولید شده، اجازه دهید به اصول تست بار نگاه کنیم.
در اسناد راهنمای NBomber توضیحات خوب و کاملی در مورد اصول اولیه تست بار وجود دارد. من سعی میکنم در اینجا به خلاصه ای از آنها اشاره کنم:
مهمترین معیارهای تست بار:
ابتدا نگاهی به آمار تولید شده در محله قبل داشته باشیم:
┌────────────────────┬────────────────────────────────────────────────────────┐
│ step │ ok stats │
├────────────────────┼────────────────────────────────────────────────────────┤
│ name │ fetch_html_page │
│ request count │ all = 662, ok = 662, RPS = 11 │
│ latency │ min = 59,66, mean = 90,47, max = 367,5, StdDev = 32,04 │
│ latency percentile │ 50% = 79,61, 75% = 92,48, 95% = 158,98, 99% = 209,15 │
└────────────────────┴────────────────────────────────────────────────────────┘
Request count
RPS
all
ok
Latency
Latency percentile
تعداد کاربران ثابتی دارند، هر کاربر یک درخواست ارسال می کند و سپس منتظر پاسخ می ماند.این ارتباط بین API و Database خواهد بود. بنابر این پایگاه داده یک سیستم بسته است.
تعداد کابران مشخص نیست. هرچیزی که از پروتکل هایی مانند HTTP استفاده میکند باید یک سیستم باز در نظر گرفته شود(مانند وب سایت ها).
بر اساس این دانش نامه ما بعدا شبیه سازی صحیح را برای سیستم خود انتخاب خواهیم کرد. برای سیستم های بسته پارامتر های شبیه سازی می تواند بصورت ثابت در نظر گرفته شود، اما پیشنهاد من برای سیستم های باز استفاده از پارامتر های تصادفی است.