JMeter के साथ लोड टेस्टिंग
JMeter एक बेहतरीन टेस्टिंग टूल है। यह खास तौर पर लोड टेस्ट के दौरान बहुत कारगर साबित होता है। आप न केवल अलग-अलग इंटरफेस का उपयोग करके एप्लिकेशन या डेटाबेस के परफॉर्मेंस को टेस्ट कर सकते हैं, बल्कि आप समानांतर यूजर्स की भीड़ का अनुकरण करके विभिन्न स्तरों का लोड भी उत्पन्न कर सकते हैं। उपयोग के मामले के आधार पर, आप अलग-अलग स्थितियों का परीक्षण करना चाह सकते हैं, जैसे:
- अधिकतम लोड जिसे सिस्टम झेल सकता है;
- कौन सा कंपोनेंट बॉटलनेक है:
- डेटाबेस;
- बैकएंड;
- माइक्रोसर्विसेज में एक विशिष्ट नोड;
- फ्रंटएंड;
- क्या सिस्टम स्केलेबल है (वर्टिकली/हॉरिजॉन्टली);
- क्या लोड बैलेंसिंग सही तरीके से काम कर रही है;
- क्या सिस्टम बेहतर ढंग से कॉन्फ़िगर किया गया है और विभिन्न कंपोनेंट्स में बेहतर ढंग से स्केल्ड है।
विश्लेषण
टेस्ट तैयार करने से पहले, आपको यह विश्लेषण करना चाहिए कि आपका सिस्टम कैसे उपयोग किया जाता है और सबसे आम उपयोग के मामले क्या हैं। किसी भी बैकग्राउंड टास्क और किसी भी विशिष्ट मेथड को याद रखना महत्वपूर्ण है, जो बहुत कम उपयोग किए जा सकते हैं, लेकिन लोड बढ़ने के साथ, आपके सिस्टम को जाम कर सकते हैं। यह परिभाषित करने के बाद कि कौन से इंटरफेस का परीक्षण किया जाना चाहिए, और उनके उपयोग का अनुपात क्या है, अगला कदम निष्पादन क्रम और अवधि की योजना बनाना है। पर्याप्त समय चुनने पर विचार करें ताकि गारबेज कलेक्टर कई बार लागू हो सके। डेटाबेस या आपकी कैशिंग लेयर के लिए सबसे खराब स्थिति प्राप्त करने के लिए कुछ विविधता की भी आवश्यकता हो सकती है। अंत में - समानांतर थ्रेड्स (उपयोगकर्ताओं) की संख्या जो सिस्टम पर हिट करेगी, लोड वृद्धि के साथ योजना बनाई जानी चाहिए।
कुछ अन्य विषय जिन पर विचार करना उचित है:
- टेस्ट किस वातावरण में चलाए जाएंगे:
- कनेक्शन;
- हार्डवेयर;
- सॉफ्टवेयर;
- कॉन्फ़िगरेशन;
- प्रोडक्शन से तुलना;
- क्या बैकअप की आवश्यकता है;
- क्या एक पीसी पर्याप्त लोड उत्पन्न करने में सक्षम होगा;
- क्या सभी लोग टेस्ट चलाने के लिए पहले से प्रशिक्षित हैं और उनके पास आवश्यक पहुंच है;
- निगरानी के उद्देश्यों के लिए कौन से अन्य उपकरण आवश्यक हैं (जैसे Zipkin/Kibana/Nagios);
- इनपुट डेटा कैसे लोड किया जाएगा:
- टेस्ट के दौरान डेटाबेस से;
- टेस्ट स्टार्टअप पर डेटाबेस से;
- इनपुट फ़ाइल से;
- वास्तविक उद्देश्य क्या है;
- परिणामों का विश्लेषण कैसे करें और किस प्रकार की रिपोर्ट बनाएं।
जैसा कि आप देख सकते हैं, बहुत सारे खुले बिंदु हैं जिन्हें विश्लेषण के दौरान स्पष्ट किया जाना चाहिए। एक उचित योजना सार्थक परिणाम प्राप्त करने के लिए आवश्यक है जो भविष्य के परीक्षणों के साथ तुलना करने की अनुमति देगा।
सैंपल इम्प्लीमेंटेशन
लोड टेस्ट के एक बुनियादी कार्यान्वयन में निम्नलिखित चरण और तत्व शामिल हैं:
- इंटरफेस से कनेक्शन को कॉन्फ़िगर करना (वैकल्पिक रूप से पैरामीटराइज़ करना) [Test Plan/User Variables Config/Config Defaults]।
- इनपुट डेटा लोड करना [setUp Thread Group]:
- डेटाबेस से [JDBC Config/Sampler];
- CSV फ़ाइल से [CSV Config]।
- इंटरफेस को कॉल करने वाले टेस्ट केस तैयार करना [Thread Group]:
- एक ही निष्पादन के लिए इनपुट डेटा को रैंडमाइज करना [CSV Config/JSR223 Pre Processor];
- आनुपातिक रूप से रैंडमाइज करना कि कौन सा इंटरफ़ेस कॉल करना है [Controllers];
- अतिरिक्त आवश्यकताओं को परिभाषित करना:
- छोटी पीक्स प्राप्त करने के लिए इकट्ठा करने के लिए थ्रेड्स की संख्या [Timers];
- अतिरिक्त इंटरफ़ेस कॉल जो परिदृश्य में होने की उम्मीद है [Samplers]।
- टेस्ट की निगरानी के लिए एक एग्रीगेट व्यू जोड़ना [Listeners]।
ध्यान दें कि टेस्ट जितने सरल होंगे, वे उतनी ही तेजी से निष्पादित होंगे और एक बड़ा लोड उत्पन्न किया जा सकता है। साथ ही, उन्हें सरल बनाकर, आप संभावित विफलता बिंदुओं की संख्या कम कर सकते हैं। उदाहरण के तौर पर चरण 2 को लेते हैं। यदि हम अपने परीक्षणों में डेटाबेस से कनेक्ट करने का निर्णय लेते हैं तो हम परीक्षणों और निर्भरताओं की जटिलता को बढ़ाते हैं। उदाहरण के लिए, परीक्षणों के अंदर डेटाबेस का पासवर्ड संग्रहीत करने की अनुशंसा नहीं की जाती है। आप उन्हें समीक्षा के लिए साझा करना चाह सकते हैं, रिपॉजिटरी पर अपलोड कर सकते हैं या उन लोगों को दे सकते हैं जो उन्हें ऑफ-आवर्स के दौरान निष्पादित करेंगे। हर कोई जिसके पास उन तक पहुंच है, उसके पास डेटाबेस तक पहुंच भी नहीं है/होनी चाहिए। गलत क्रेडेंशियल प्रदान करना और कुछ समय खोना भी संभव है, खासकर जब आपके पास परीक्षणों को निष्पादित करने के लिए एक सीमित समय खिड़की हो।
एक और समस्या तब हो सकती है जब आप टेस्ट प्लान निष्पादन की संख्या बढ़ाकर (कई लोग/मशीनें) बहुत बड़ा लोड उत्पन्न करना चाहेंगे। यदि आप इनपुट डेटा के लिए डेटाबेस क्वेरी को सिंक्रनाइज़ नहीं करते हैं, तो यह संभव है कि एप्लिकेशन सभी डेटाबेस संसाधनों (कनेक्शन) का उपयोग कर ले। इस मामले में, आपको सेट-अप चरण के दौरान टाइमआउट मिल सकता है जो प्रभावी रूप से अगले चरणों को अविश्वसनीय बना देता है। तो, ऐसे मामले में पहले से प्राप्त (जैसे एक दिन पहले) इनपुट डेटा लोड करना बेहतर है। हालांकि, यदि आपके पास समय की कमी नहीं है, तो आप स्वयं चीजों का परीक्षण कर सकते हैं।
एक अनुकरणीय कार्यान्वयन के लिए, आप पृष्ठ के नीचे दिए गए स्रोतों की जांच कर सकते हैं। प्रोजेक्ट में स्प्रिंग में लागू एक REST API है और इसमें कुछ सरल लोड टेस्ट शामिल हैं। कृपया उचित सेट-अप के लिए README पढ़ें (डेटाबेस ड्राइवर को डाउनलोड करके JMeter क्लासपाथ में डालना होगा)।
JMeter वेरिएबल्स स्कोप
JMeter में वेरिएबल्स प्रति थ्रेड स्कोप किए जाते हैं। इसका मतलब यह है कि यदि आप setUp Thread Group में डेटा लोड करते हैं तो यह इंटरफेस को कॉल करने के लिए जिम्मेदार संबंधित थ्रेड ग्रुप्स के लिए सुलभ नहीं होगा। बेशक, आप लोडिंग लॉजिक को उनके अंदर रख सकते हैं, लेकिन कुछ स्थितियों में, यह संभव नहीं हो सकता है। आप परीक्षण समय के दौरान डेटाबेस पर कोई कृत्रिम भार उत्पन्न नहीं करना चाह सकते हैं। ऐसे मामले में आप JMeter प्रॉपर्टीज का उपयोग करके काम चला सकते हैं, जो Thread Groups के बीच साझा की जाती हैं। setUp थ्रेड में प्रॉपर्टी को सेव करने के लिए उपयोग करें:
- __setProperty फ़ंक्शन;
- JSR223 Sampler/पोस्ट प्रोसेसर और JMeterProperties props ऑब्जेक्ट
java.util.Propertiesइंटरफ़ेस के साथ - JDBC परिणाम सेट वेरिएबल्स को सहेजने की अनुमति देता है।
इन गुणों को पढ़ना उतना ही सरल है जितना उपयोग करना:
- __P या __property फ़ंक्शन;
- JSR223 Sampler/प्री प्रोसेसर और props ऑब्जेक्ट।
प्रॉपर्टीज का उपयोग -J उपसर्ग के साथ कमांड लाइन में पास किए गए पैरामीटर को पुनः प्राप्त करने के लिए भी किया जाता है, जैसे -Jparameter=value।
डेटा को रैंडमाइज करना
इनपुट डेटा साझा करने के बाद, आप इसे एक ही निष्पादन के लिए रैंडमाइज कर सकते हैं और आवश्यक जानकारी को एक वेरिएबल में सहेज सकते हैं। यह बाद में उसी थ्रेड ग्रुप में ${variable_name} सिंटैक्स का उपयोग करके सुलभ होगा और प्रत्येक थ्रेड में प्रभावी रूप से एक अलग इनपुट होगा।
import java.util.Random;
Random rand = new Random();
def index = rand.nextInt(props.get("resultSet").size());
vars.put("id", props.get("resultSet").get(index).get("USER_ID").toString());
आप रैंडम नंबर उत्पन्न करने के अन्य तरीकों की तुलना भी करना चाह सकते हैं। मैंने कुछ परफॉर्मेंस टेस्ट चलाए हैं जिनमें एक रैंडम पूर्णांक उत्पन्न करना और लॉग करना शामिल है। ध्यान दें कि उन्हें एक ढीले तरीके से निष्पादित किया गया था और केवल त्वरित संदर्भ के लिए हैं (10 थ्रेड्स x 100000 दोहराव):
| रैंडमाइज़र | थ्रूपुट [एग्जेक/सेकंड] | नोट |
|---|---|---|
| java.util.Random | 10900 | - |
| java.util.concurrent.ThreadLocalRandom | 11377 | java.util.Random के समान प्रदर्शन यह दर्शाता है कि निष्पादन पहले से ही थ्रेड ग्रुप में थ्रेड लोकल है (स्क्रिप्ट के अंदर थ्रेड पूल में कोई स्पष्ट निष्पादन नहीं है) |
| org.apache.commons.lang3.RandomUtils | 11704 | बहुत छोटे अंतर (1%) से सबसे तेज |
| __Random | 5065 | दोगुना धीमा |
जैसा कि आप देख सकते हैं, पहले तीन तरीकों में से कोई भी एक वैध विकल्प है। मैं __Random का उपयोग करने की अनुशंसा नहीं करूंगा क्योंकि यह किसी तरह बहुत धीमा लगता है। हालाँकि, डमी डेटा उत्पन्न करने के लिए __RandomString, __RandomDate, __time, और __threadNum जैसे अन्य बहुत आसान फ़ंक्शन हैं। ग्रूवी कोड को __groovy का उपयोग करके भी इनलाइन किया जा सकता है।
लोड बढ़ाना
लोड को पैरामीटराइज़ करते समय, और प्रति सेकंड अनुरोधों की लक्षित राशि, आप परीक्षण के तहत अपने घटकों के कुछ कॉन्फ़िगरेशन गुणों को नोट करना चाह सकते हैं। डेटाबेस के मामले में, यह कनेक्शन की अधिकतम संख्या है। सर्वरों के लिए, यह समानांतर अनुरोधों की संख्या और कतार का आकार है। इसे नोड्स की संख्या से गुणा करें और कुछ ओवरहेड को ध्यान में रखें।
जैसा कि पहले उल्लेख किया गया है, लोड बढ़ाना उतना ही सरल है जितना उपयोगकर्ताओं की संख्या बढ़ाना। आपकी मशीन विनिर्देश और परीक्षण कार्यान्वयन के आधार पर, आप लगभग 5000 समानांतर थ्रेड्स सेट-अप कर पाएंगे। हालाँकि, किसी बिंदु पर, अतिरिक्त थ्रेड बनाने का ओवरहेड प्रभावी रूप से प्रदर्शन को कम कर देगा, संभवतः परीक्षण निष्पादित करने वाली मशीन को फ्रीज भी कर देगा। यदि आपके पास एक उच्च-प्रदर्शन वाला मल्टी-नोड सिस्टम है, तो अधिकतम लोड सीमा प्राप्त करने के लिए यह पर्याप्त नहीं हो सकता है। ध्यान दें कि उपयोगकर्ताओं की संख्या के आधार पर, प्रति यूनिट समय में इंटरफ़ेस निष्पादन की संख्या का अनुमान लगाना भी कठिन है। डिफ़ॉल्ट रूप से, प्रत्येक थ्रेड को इंटरफ़ेस पर एक अनुरोध भेजना होता है और प्रतिक्रिया की प्रतीक्षा करनी होती है।
एक प्रतिक्रिया टाइमआउट सेट करके हम प्रभावी रूप से प्रतिक्रिया की प्रतीक्षा करना छोड़ सकते हैं, और अगला अनुरोध तेजी से शुरू कर सकते हैं। इसकी कमी यह है कि आप प्रतिक्रियाओं और उनकी स्थितियों की निगरानी की संभावना खो देंगे। यह एक वैध विकल्प है यदि आपके पास लोड की निगरानी के लिए अलग-अलग उपकरण हैं। वास्तव में कम प्रतिक्रिया टाइमआउट सेट करते समय, मैं स्थिति जांच के लिए एक अनकॉन्फिगर थ्रेड ग्रुप को छोड़ने की भी सलाह देता हूं। आप किसी अज्ञात फ़ायरवॉल द्वारा अवरुद्ध हो सकते हैं और इसका एहसास नहीं होगा, खासकर यदि निगरानी उपकरण ऑनलाइन डेटा प्रदर्शित नहीं करते हैं।
विचार करने वाली अंतिम बात कनेक्शन है। स्थानीय नेटवर्क में, आपको आमतौर पर सर्वर तक पहुंचने में बहुत कम समय मिलेगा। यदि लक्ष्य वातावरण इंटरनेट में है या केवल वीपीएन के माध्यम से पहुँचा जा सकता है, तो परीक्षण धीमे होंगे, प्रभावी रूप से कम भार उत्पन्न करेंगे। अंत में, बैंडविड्थ को न भूलें, जो अक्सर सीमित कारक होता है।
सारांश
JMeter लोड टेस्टिंग के लिए एक अच्छा टूल है, हालाँकि, इसे अतिरिक्त निगरानी टूल के साथ जोड़ा जाना चाहिए। परीक्षणों को सार्थक बनाने के लिए विचार करने के लिए बहुत सी बातें हैं। तैयारी के दौरान प्रत्येक मामले को पहचाना जाना चाहिए। एक सफल परीक्षण चलाने के बाद, यह रिपोर्ट का विश्लेषण करने और तैयार करने का समय है। SLA को पूरा करने या परिभाषित करने के लिए भविष्य के कदम परिभाषित करने में यह एक अनिवार्य हिस्सा है।
सैंपल प्रोजेक्ट को देखना न भूलें। आप Tomcat थ्रेड पूल, कतार आकार, H2 डेटाबेस कनेक्शन पूल आकार, और टाइमआउट मानों के लिए डिफ़ॉल्ट संख्या का पता लगाने वाले परीक्षणों के साथ खेल सकते हैं। CSV/डेटाबेस से डेटा लोड करना, वेरिएबल्स स्कोप और लोड बढ़ाना जैसे विषय भी वहां शामिल हैं।
