Java सर्वलेट्स: इंस्टेंस, सेशन और मल्टीथ्रेडिंग - पूरी गाइड

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

सर्वलेट्स अब भी क्यों डराते हैं, और इससे कैसे निपटें?

\n\n

अगर आपने कभी Stack Overflow पर "सर्वलेट्स कैसे काम करते हैं?" सवाल का जवाब ढूंढा है, तो आपने शायद वह famous थ्रेड देखा होगा जिसे हज़ारों बार देखा गया है। वह सवाल जो बार-बार पूछा जाता है: "सर्वलेट के कितने इंस्टेंस बनते हैं? रिक्वेस्ट के बीच डेटा कैसे शेयर करें? और मेरा वेरिएबल पागलों की तरह क्यों व्यवहार कर रहा है?"

\n\n

सच कहूं तो: सर्वलेट्स कोई rocket science नहीं हैं, लेकिन इनमें कई छिपे हुए खतरे हैं। खासकर जब बात आती है मल्टीथ्रेडिंग और शेयर्ड वेरिएबल्स की। इस लेख में हम सिर्फ डॉक्यूमेंटेशन नहीं दोहराएंगे। हम एक real-life उदाहरण लेंगे, उसे टुकड़ों में समझेंगे और दिखाएंगे कि गलतियों से कैसे बचें। चलिए शुरू करते हैं!

\n\n

सर्वलेट मेमोरी में कैसे आता है: इंस्टेंसिएशन और लाइफ साइकिल

\n\n

चलिए सबसे सरल से शुरू करते हैं: सर्वलेट के कितने इंस्टेंस बनते हैं? जवाब: एक। हाँ, आपने सही सुना। सर्वलेट कंटेनर (Tomcat, Jetty आदि) पूरे एप्लिकेशन के लिए प्रत्येक सर्वलेट का सिर्फ एक इंस्टेंस बनाता है। और यह इंस्टेंस तब तक जीवित रहता है जब तक एप्लिकेशन अनलोड न हो जाए।

\n\n

यहाँ typical life cycle दिया गया है:

\n\n
    \n
  • init() — सर्वलेट लोड होने पर एक बार कॉल होता है। यहाँ आप DB कनेक्शन, कॉन्फ़िगरेशन आदि initialize करते हैं।
  • \n
  • service() — हर incoming request के लिए कॉल होता है। यहीं पर प्रोसेसिंग होती है।
  • \n
  • destroy() — सर्वलेट अनलोड होने से पहले कॉल होता है। रिसोर्सेज़ को साफ करें।
  • \n
\n\n

मुख्य बात: service() (और इसके डेरिवेटिव doGet, doPost) हर request के लिए एक अलग thread में execute होता है। यानी एक ही सर्वलेट इंस्टेंस सैकड़ों requests को एक साथ प्रोसेस करता है। और यहीं से मज़ा शुरू होता है।

\n\n

उदाहरण: एक सर्वलेट, कई threads

\n\n
@WebServlet("/counter")\npublic class CounterServlet extends HttpServlet {\n    private int counter = 0;  // shared variable!\n\n    @Override\n    protected void doGet(HttpServletRequest req, HttpServletResponse resp) \n            throws ServletException, IOException {\n        counter++;\n        resp.getWriter().write("Counter: " + counter);\n    }\n}
\n\n

अगर आप यह कोड चलाते हैं और 10 parallel requests भेजते हैं, तो आपको 1 से 10 तक के क्रम में नंबर नहीं मिलेंगे। इसके बजाय आप कुछ ऐसा देखेंगे: 2, 5, 3, 8, 1... या counter कुछ वैल्यूज़ को छोड़ भी सकता है। क्यों? क्योंकि counter++ एक atomic operation नहीं है। दो threads एक ही वैल्यू पढ़ सकते हैं, उसे बढ़ा सकते हैं और वापस लिख सकते हैं, जिससे एक increment खो जाता है।

\n\n

निष्कर्ष: सर्वलेट के instance fields shared variables हैं। ये सभी threads को दिखाई देते हैं। और अगर आप इन तक access को synchronize नहीं करते, तो race condition होगी।

\n\n

सेशन: यूज़र्स को कैसे न मिलाएं

\n\n

अब सोचिए: आप हर यूज़र के लिए unique डेटा स्टोर करना चाहते हैं (शॉपिंग कार्ट, लॉगिन, सेटिंग्स)। इसके लिए Java Servlets में HttpSession है। हर नए यूज़र के लिए एक सेशन बनता है और वह तब तक जीवित रहता है जब तक यूज़र ब्राउज़र बंद न करे या timeout न हो जाए।

\n\n

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

\n\n

उदाहरण: सेशन के साथ काम करना

\n\n
@WebServlet("/session-demo")\npublic class SessionServlet extends HttpServlet {\n    @Override\n    protected void doGet(HttpServletRequest req, HttpServletResponse resp) \n            throws ServletException, IOException {\n        HttpSession session = req.getSession();\n        Integer visitCount = (Integer) session.getAttribute("visitCount");\n        if (visitCount == null) {\n            visitCount = 0;\n        }\n        visitCount++;\n        session.setAttribute("visitCount", visitCount);\n        resp.getWriter().write("आपने इस पेज को " + visitCount + " बार देखा है");\n    }\n}
\n\n

यह कोड हर यूज़र के लिए अलग-अलग visit count रखेगा। कोई race condition नहीं, क्योंकि हर यूज़र की अपनी सेशन है।

\n\n

ServletContext बनाम HttpSession: कब क्या इस्तेमाल करें?

\n\n

अब एक और important concept: ServletContext। यह पूरे एप्लिकेशन के लिए एक सिंगल ऑब्जेक्ट है। इसे सभी सर्वलेट्स और सभी यूज़र्स शेयर करते हैं। इसका उपयोग global settings, database connection pools, या ऐसे डेटा के लिए करें जो सभी यूज़र्स के लिए समान हो।

\n\n

याद रखें: ServletContext में स्टोर किया गया डेटा thread-safe होना चाहिए, क्योंकि कई threads एक साथ इसे access कर सकते हैं।

\n\n

निष्कर्ष: सर्वलेट्स को समझना आसान है

\n\n

सर्वलेट्स को समझने के लिए बस तीन चीज़ें याद रखें:

\n\n
    \n
  1. एक सर्वलेट = एक इंस्टेंस। सभी requests एक ही इंस्टेंस पर आती हैं।
  2. \n
  3. Instance fields = shared variables। इन्हें thread-safe बनाएं या इनका उपयोग न करें।
  4. \n
  5. HttpSession = per-user storage। यूज़र-विशिष्ट डेटा के लिए सेशन का उपयोग करें।
  6. \n
\n\n

अब आप बिना किसी डर के सर्वलेट्स के साथ काम कर सकते हैं। हैप्पी कोडिंग!

ब्लॉग

पुस्तक अनुशंसाएँ