مروری بر جیمیتر

تست کارایی و تست بار چیست؟
تست کارایی نام عمومی تستهایی است که نحوه رفتار و عملکرد سیستم را تحت بار خاصی بررسی میکنند. این تست به منظور یافتن اشکالات نرمافزاری استفاده نمیشود، بلکه یک تکنیک تست نرمافزاری غیر عملکردی(non-functional) است که تعیین میکند چگونه پایداری ،سرعت ، مقیاس پذیری و پاسخگویی یک برنامه، تحت حجم کاری معینی حفظ میشود. این یک گام کلیدی برای اطمینان از کیفیت نرمافزار قبل از استقرار نهایی آن است. برای سیستمهای بزرگی که تعداد زیادی کاربر همزمان از آن ها استفاده میکنند،اندازهگیری و بررسی نحوه برخورد آنها با حجم بارهای زیاد بسیار حائز اهمیت است. در واقع تست بار نوعی آزمایش کارایی میباشد که تعداد زیادی کاربر همزمان را شبیه سازی کرده و سپس نحوه عملکرد سیستم را در مدت زمان معینی بررسی میکند. در نهایت با آنالیز نتایج میتوان تصمیم گرفت که آیا سیستم عملکرد قابل قبولی خواهد داشت و یا خیر و در صورت عملکرد ضعیف سیستم، میتوان برای بهبود آن برنامهریزی کرد. برای انجام تست بار، چندین ابزار منبع باز وجود دارد که JMeter محبوبترین آنهاست. JMeter یک ابزار متنباز و مبتنی بر Java میباشد که نتایج رفتار مرورگر را با ارسال درخواست به سرورهای وب یا برنامه شبیهسازی میکند.در این پست به آموزش اولیه در مورد نحوه کار با JMeter و همچنین نحوه انجام یک تست بار ساده میپردازیم. جهت آشنایی بیشتر با این ابزار و اطلاع از مزایا و معایب آن میتوانید به مقاله مقدمه و آشنایی با جیمیتر و مزایا مراجعه کنید.
بررسی سیستم مورد آزمون (SUT)
در این مقاله برای آموزش بهتر سعی میکنیم یک تست بار ساده را بر روی یک سیستم واقعی انجام دهیم. سیستم مورد آزمون ما در اینجا سایت دیوار است. با ورود به صفحه فروش آپارتمان در مرورگر خود یک درخواست از نوع HTTP با متد Get به سمت سرور ارسال و پاسخ آن از سرور دریافت میشود. با مراجعه به بخش developer tools در مرورگر خود میتوان URL مربوطه را مشاهده کنید. این آدرس به صورت زیر است:
https://api.divar.ir/v8/web-search/tehran/buy-apartment
با توجه به این که تعداد کاربران زیادی به صورت همزمان از این صفحه استفاده میکنند تا لیست آگهیهای فروش آپارتمان را در سایت دیوار مشاهده کنند، قصد داریم که فرایند تست بار بر روی این درخواست را بررسی کنیم. یعنی کاربران مجازی را شبیهسازی کنیم که بصورت همزمان به این آدرس مراجعه کرده و از صفحه « فروش آپارتمانهای دیوار» دیدن میکنند.

تست بار ساده سایت دیوار
نصب و پیکربندی:
در ابتدا نیاز است که جیمیتر را دانلود و راهاندازی کنید. برای آشنایی کامل با این مرحله میتوانید از مقاله نصب و پیکربندی جیمیتر استفاده نمایید.
طرح تست یا Test Plan
پس از اجرای جیمیتر صفحهای مشابه شکل زیر نمایش داده میشود که شامل یک Test Plan میباشد. Test Plan کامپوننت اصلی جیمیتر است، در واقع مانند ظرفی است که شامل المانهای مورد نیاز برای اجرای تست میباشد و جریان تست بار شما را نمایش میدهد. یک Test Plan کامل از یک یا چند المان مانند Thread Group ،Logic Controllers، Samplers، Listeners، Timers، Assertions و Configuration Elements تشکیل میشود. در نظر داشته باشید که هر Test Plan باید حداقل یک Thread Group داشته باشد.

گروه کاربران یا Thread Group
Thread Group جریان کاربران و رفتار آنها را در برنامه شبیهسازی کرده و تعداد آنها را در طول تست کنترل میکند. در واقع هر thread نشان دهنده یک کاربر است. Thread Groupهای متعددی در دسترس هستند که نحوه تعامل کاربران با برنامه ، چگونگی حفظ بار و مدت زمان اجرا را شبیهسازی میکنند. برای ساخت و طراحی یک تست ابتدا یک Thread Group به Test Plan اضافه کنید. روی Test Plan کلیک راست کرده و از مسیر Add ->Threads (Users) ->Thread Group آن را به تست اضافه کنید.

سپس Thread Group را با توجه به نیازمندی های خود پیکربندی کنید:
- Name: یک نام مشخص برای Thread Group تعیین کنید. به عنوان مثال این مقدار را «divar-thread-group» میگذاریم.
- Number of Threads: تعداد کاربرانی که میخواهید همزمان از سیستم استفاده کنند را در این قسمت مشخص کنید. با توجه به اینکه این یک تست آزمایشی است و ما نمیخواهیم ترافیک زیادی به سایت دیوار منتقل کنیم حداکثر مقدار 10 کاربر همزمان را در آن تنظیم میکنیم.
- Ramp-up Period: این فیلد مدت زمانی (در ثانیه) که می خواهید کاربران همزمان را به تست اضافه کنید، مشخص میکند. به عنوان مثال، اگر این متغیر روی صفر تنظیم شود، همه کاربران بلافاصله شروع به کار میکنند. اگر روی 10 تنظیم شود، تعداد کاربران همزمان را در طول 10 ثانیه اضافه میکند. در این مثال ما این عدد را بر روی 10 ثانیه قرار میدهیم. در نتیجه چون تعداد کاربران همزمان نیز بر روی 10 تنظیم شده است، یعنی تقریبا هر ثانیه یک کاربر اضافه میشود تا طی مدت 10 ثانیه مجموع کاربران همزمان ما به 10 عدد برسد.
- Loop Count: تعداد دفعاتی که میخواهیم سناریوی تست اجرا شود. به عبارتی دیگر هر کاربر مجازی چند بار سناریوی آزمون خود را اجرا کند. مثلا در مثال ما هر کاربر مجازی، درخواست دیدن صفحه آگهی فروش آپارتمان در دیوار را انجام میدهد. این عدد تعیین میکند این کاربر چند بار این عمل را در طول تست انجام دهد. همچنین میتوان با انتخاب گزینه infinite این تعداد را بینهایت دانست. در چنین حالتی تا زمانی که تست ادامه دارد (تا زمانی که تست توسط ما بصورت دستی قطع نشود) کاربر مجازی عمل مورد نظر را انجام میدهد.
- Specify Thread lifetime: با انتخاب این گزینه میتوانید در بخش Duration مدت زمان اجرای تست را مشخص کنید. با اتمام این زمان تست به صورت خودکار متوقف میشود.

نمونهگیر یا Sampler
برای ارسال درخواست های مختلفی به سرور و دریافت نتیجه به Thread Group اضافه میشود. از آنجا که Sampler بعد از ارسال درخواست و دریافت نتیجه، متریکهایی همچون درستی این عمل، زمان طول کشیدن عملیات و جزيبات دیگری را ثبت میکند به آن نمونهگیر میگویند. در واقع از مجموع نمونههای جمعآوری شده در طول آزمون در نهایت نتایج آزمون استخراج میشود. JMeter از تست HTTP ، FTP ، JDBC و بسیاری از پروتکلهای دیگر پشتیبانی میکند. با توجه به اینکه ما میخواهیم یک HTTP Request ارسال کنیم، بنابراین یک HTTP Request Sampler به Thread Group اضافه میکنیم. روی Thread Group کلیک راست کرده و از مسیر Add -> Sampler ->HTTP Request آن را به تست خود بیافزایید.

برای تکمیل مثال تست سایت دیوار، در این بخش نیاز است که برای درخواست دریافت لیست آگهی ها یک HTTP Request را به Thread Group اضافه کنید. سپس Sampler خود را با توجه به موارد زیر تنظیم کنید (در عکس زیر مقادیر لازم برای این بخش نشان داده شده است):
- Name: میتوانید یک نام مشخص برای Sampler تعیین کنید.
- Protocol: با توجه به نوع پروتکل درخواست مورد نظر، این فیلد را پر کنید. در این جا پروتکل درخواست دریافت آگهی ها https است و این فیلد را برابر با https قرار دادیم.
- Server Name or IP: آدرس سرور و یا آدرس IP را در این بخش مینویسیم.
- HTTP Request: متد API مورد نظر را مشخص میکنیم که در اینجا GET میباشد.
- Path: در این بخش endpoint درخواست را مشخص مینماییم.

المان پیکربندی یا Config Element
با استفاده از Configuration Element می توان پیش فرض ها و متغیرهایی که توسط Sampler استفاده میشوند را ایجاد کنید. آنها قبل از هر Sampler ای که در یک scope قرار دارند اجرا میشوند.اگر یک Config Element در یک node از یک درخت تعریف شده باشد در زمان اجرا اولویت بیشتری نسبت به Config Element مشابه خود در لایه های بالاتر دارد. همچنین یک Config Element فقط داخل شاخه ای که در آن قرار دارد قابل دسترسی است.طبق شکل زیر، از مسیر Add -> Config Element می توان انواع Config Element ها را به Sampler اضافه کرد.

Config Elementها انواع مختلفی دارن که یکی از مهمترین آنها HTTP Header Manager است. در هر HTTP Header Manager میتوان هدرهای مورد نیاز هر درخواست رامشخص کرد. در هنگام ارسال هر درخواست به سرور، این مقادیر در بخش هدردرخواست به سرور ارسال میشوند. انواع مختلفی از هدرها موجود میباشد که میتوان به User-Agent، Accept، Content-Type و … اشاره کرد. این مقادیر را میتوانید در بخش Request Header در تب Network مشاهده کنید.

در ادامهی تکمیل مثال سایت دیوار، برای تنظیم کردن Header درخواست، یک HTTP Header Manager به Sampler اضافه کردیم و هدرهای مورد نیاز را مشخص نمودیم.

تاییدیه یا Assertion
Assertionها به شما اجازه می دهند پاسخ درخواستهایی که به سمت سرور ارسال کردید را ارزیابی و تایید کرده و برای مقایسه نتیجه واقعی و نتیجه مورد انتظار تست از آن ها استفاده کنید. انواع مختلفی Assertion وجود دارد که برای اهداف خاصی طراحی شدهاند. برای اضافه کردن آن، روی Sampler کلیک راست کرده و از مسیر Add -> Assertions یک Assertion به Sampler اضافه کنید. درخواست دریافت لیست آگهیهای سایت دیوار اگر با موفقیت اجرا شود response code آن برابر 200 خواهد بود. بنابراین یک Response Assertion اضافه میکنیم و مقادیر فیلدهای آن را طبق شکل زیر مشخص میکنیم:

پس از اجرای این درخواست، اگر response code چیزی غیر از 200 باشد، این Assertion رد میشود و مشخص میشود که این درخواست به درستی اجرا نشده است و به عنوان خطا در نتایج ثبت میشود. سپس میتوانید علت اجرای نادرست را بررسی کنید.همچنین میتوانید Response Message و موارد دیگری را هم با استفاده از این Assertion ارزیابی کنید. مثلا اینکه در پاسخ عبارت مورد انتظاری وجود داشته باشد.
تایمر یا Timer
وقتی کاربران با وب سایت یا برنامه شما کار می کنند ، طبیعتاً مکث و تاخیر دارند. این زمان را میتوان با تایمر شبیهسازی کرد. با کمک تایمر میتوانید مدت زمان تاخیر را از یک درخواست به درخواست دیگر تنظیم کنید. گاهی به این زمان تاخیر بین درخواستهای کاربر زمان تفکر یا thick time نیز میگوییم. مثلا چه مدت زمانی برای انتقال از صفحه اصلی به صفحه دیگر نیاز دارید. Constant Timers یا تایمرهای ثابت یکی از پرکاربردترین تایمرها محسوب میشود. روی HTTP Request کلیک راست کرده و از مسیر Add -> Timers -> Constant Timers آن را انتخاب کنید. در این مثال ما 300 میلی ثانیه بین هر درخواست صبر میکنیم.

شنوندهها یا Listeners
پس از اجرای تست نتایج را میتوان با استفاده از Listener ها مشاهده نمود. شنوندهها درواقع به سمپلهای گرفته شده گوش میدهند و میتوانند آنها را جمعآوری کنند، آنها را نمایش دهند یا نتایج کلی و جزئی آزمون را از آنها استخراج کنند. آن ها را میتوان به هر کدام از کامپوننتها از جمله Thread Group اضافه کرد. Listener ها انواع مختلفی دارند که نتایج را میتوانند به صورت درخت، جدول، گراف و یا در یک فایل نمایش دهند. View Results Tree یکی از رایجترین آنها میباشد که نتایج را بصورت جزیی نمایش میدهد. برای تکمیل مثال خود، با کلیک راست روی Thread Group و از مسیر Add -> Listeners ->View Results Tree میتوان آن را به Thread Group افزود. همچنین ما یک Summary Result هم اضافه میکنیم که وظیفه آن استخراج نتایج خلاصه و کلی آزمون است. در این listener سطری به تفکیک درخواستها و یا تراکنشها ایجاد میشود و نتایج را برای تمام درخواستهای مشابه به صورت خلاصه نشان میدهد.

اجرای تست
در بخشهای قبل یک آزمون کارایی ساده برای دیدن آگهیهای سایت دیوار طراحی کردیم. پیش از اجرا لازم است فایل طراحی شده را ذخیره کنیم. پس بر روی آیکون save در جیمیتر کلیک کنید. پس از مشخص نمودن مسیر ذخیره فایل، تست شما بصورت یک فایل jmx. ذخیره خواهد شد حال میتوانیم این تست را اجرا کنیم. همچنین فایل طراحی ما در مسیر مشخص شده وجود دارد که در آینده میتوان آن را اجرا کرد یا تغییراتی در طراحی ایجاد کرد.

اکنون برای اجرای تست بر روی دکمه start که در شکل زیر نشان داده شده است، کلیک میکنیم. (همچنین توجه کنید که در صورتی که قبلا تست را اجرا کردیم و دوباره میخواهیم اجرای جدیدی انجام دهیم، میتوانیم با زدن دکمه clear که با آیکون یک جارو نشان داده شده است، نتایج تست قبلی را پاک کنیم تا بتوان نتایج اجرای جدید را بصورت مشخص مشاهده کرد.)

مشاهده نتایج تست
بعد از اجرا و در حین اجرا میتوان از طریق لیسنرها نتیجه آزمون یا نتیجه درخواستها را مشاهده کرد. با رجوع به لیسنتر View Result Tree میتوان نتیجه هر درخواست را بصورت مجزا مشاهده کرد. همانطور که در شکل زیر مشاهده میکنید، تمامی درخواست ها با رنگ سبز مشخص شدند. رنگ سبز بدین معنی است که اجرای آنها موفقیت آمیز بوده است. همچنین با کلیک بر روی هر درخواست میتوان جزئیات هر درخواست (شامل آدرس درخواست، هدرها و پارامترهای درخواست) و نتیجه مربوطه را مشاهده کرد.

طبق شکل، بخشی از درخواستها با رنگ قرمز مشخص شدند. یعنی اجرای آن ها موفقیت آمیز نبوده است. در Assertion مشخص کرده بودیم که باید Response Code برابر 200 باشد ولی در اینجا Response Code 429 (Too Many Requests) دریافت کردیم. در نتیجه Assertion با شکست مواجه شده است. ارور دریافتی به این دلیل است که اگر تعداد درخواستهای ارسالی از یک ip از حدی بیشتر شود سایت آنها را بلاک میکند و به آنها پاسخ نمیدهد.

خلاصه نتایج تست
پس از پایان تست زمان آن را رسیده که نتایج را در Summary Result بررسی کنیم. همینطور که در تصویر مشاهده میکنید به ازای درخواست ارسالی یک سطر در این جدول نمایش داده شده است. همچنین یک سطر Total وجود دارد که نتیجه تست را به ازای تمام درخواستها و تراکنشها مشخص میکند. از آنجایی که در این تست فقط یک درخواست را ارسال کردیم مقادیر هر دو سطر مشابه هم میباشد.

همانطور که در تصویر بالا مشخص است این درخواست به تعداد 816 مرتبه به سرور ارسال شده است. در هر تست پارامترهای توان خروجی(Throuput)، متوسط زمان پاسخ (Average Response Time) و نرخ خطا (Error Rate) از اساسیترین و ابتداییترین نتایج تست کارایی میباشند. توان خروجی به تعداد درخواستهایی که به سرور ارسال میشود در واحد زمان گفته میشود که در این مثال برابر 13.5 میباشد. همچنین زمان پاسخ زمانی است که طول میکشد سرور به درخواست ارسالی پاسخ دهد. هر چه زمان پاسخ کمتر باشد کارایی سیستم بیشتر است. در تست اجرا شده این زمان برابر با 375 میلی ثانیه میباشد. همچنین نرخ خطا باید در کمترین میزان ممکن باشد تا تست کارایی موفقیت آمیز باشد. نرخ خطا به نسبت تعداد درخواستهایی که با خطا مواجه شدهاند به تعداد کل درخواستها گفته میشود. این مقدار همیشه به صورت درصد مشاهده میشود که در این تست 95.22٪ است. بنابراین نتیجه گرفته میشود سیستمی که نرخ خطا و زمان پاسخ کم و توان خروجی بالایی داشته باشد کارایی بالاتری دارد.