आम दृष्टिकोण, जैसा कि ओजस ने पहले ही उल्लेख किया है , एक संदेश कतार है । एक डिजाइन परिप्रेक्ष्य से एक संदेश कतार अनिवार्य रूप से एक FIFO कतार है , जो एक मौलिक डेटा प्रकार है:
मैसेज कतार को विशेष बनाता है, जबकि आपका आवेदन एन-कतारिंग के लिए जिम्मेदार है, एक अलग प्रक्रिया डी-कतारिंग के लिए जिम्मेदार होगी। कतारबद्ध लिंगो में, आपका आवेदन संदेश (नों) का प्रेषक है, और डी-कतार प्रक्रिया रिसीवर है। स्पष्ट लाभ यह है कि पूरी प्रक्रिया अतुल्यकालिक है, रिसीवर प्रेषक से स्वतंत्र रूप से काम करता है, जब तक कि प्रक्रिया करने के लिए संदेश हैं। स्पष्ट नुकसान यह है कि आपको काम करने के लिए पूरी तरह से एक अतिरिक्त घटक, प्रेषक की आवश्यकता है।
चूंकि आपका आर्किटेक्चर अब संदेशों का आदान-प्रदान करने वाले दो घटकों पर निर्भर करता है, आप इसके लिए फैंसी टर्म इंटर-प्रोसेस संचार का उपयोग कर सकते हैं ।
एक कतार शुरू करने से आपके आवेदन के डिज़ाइन पर क्या प्रभाव पड़ता है?
आपके एप्लिकेशन में कुछ क्रियाएं ईमेल उत्पन्न करती हैं। एक संदेश कतार का परिचय देने का मतलब होगा कि उन कार्यों को अब संदेश को कतार में धकेलना चाहिए (और कुछ नहीं)। उन संदेशों को पूर्ण न्यूनतम मात्रा में जानकारी ले जानी चाहिए जो आपके रिसीवर को संसाधित करने के लिए ईमेल के निर्माण के लिए आवश्यक हैं।
संदेशों का प्रारूप और सामग्री
आपके संदेशों का प्रारूप और सामग्री पूरी तरह से आपके ऊपर है, लेकिन आपको छोटे से बेहतर को ध्यान में रखना चाहिए। आपकी कतार जितनी तेजी से लिखने और प्रोसेस करने में होनी चाहिए, उतनी ही मात्रा में डेटा फेंकने से शायद अड़चन पैदा होगी।
इसके अलावा कई क्लाउड आधारित कतारबद्ध सेवाओं में संदेश आकार पर प्रतिबंध हैं और बड़े संदेशों को विभाजित कर सकते हैं। आप ध्यान नहीं देंगे, जब आप उनसे पूछेंगे तो विभाजित संदेशों को एक के रूप में परोसा जाएगा, लेकिन आपसे कई संदेशों के लिए शुल्क लिया जाएगा (यह मानते हुए कि आप एक ऐसी सेवा का उपयोग कर रहे हैं जिसके लिए शुल्क की आवश्यकता है)।
रिसीवर का डिज़ाइन
चूंकि हम एक वेब एप्लिकेशन के बारे में बात कर रहे हैं, आपके रिसीवर के लिए एक सामान्य दृष्टिकोण एक सरल क्रोन स्क्रिप्ट होगी। यह हर x
मिनट (या सेकंड) चलेगा और यह होगा:
n
कतार से संदेशों की पॉप राशि,
- संदेशों को संसाधित करें (यानी ईमेल भेजें)।
ध्यान दें कि मैं प्राप्त करने या लाने के बजाय पॉप कह रहा हूं, ऐसा इसलिए है क्योंकि आपका रिसीवर केवल कतार से आइटम प्राप्त नहीं कर रहा है, यह उन्हें भी साफ़ कर रहा है (अर्थात उन्हें कतार से हटाकर या उन्हें संसाधित के रूप में चिह्नित कर रहा है)। यह वास्तव में कैसे होगा यह संदेश कतार के आपके कार्यान्वयन और आपके आवेदन की विशिष्ट आवश्यकताओं पर निर्भर करता है।
बेशक मैं जो वर्णन कर रहा हूं वह अनिवार्य रूप से एक बैच ऑपरेशन है , एक कतार को संसाधित करने का सबसे सरल तरीका। अपनी आवश्यकताओं के आधार पर आप संदेशों को अधिक जटिल तरीके से संसाधित करना चाहते हैं (जो कि अधिक जटिल कतार के लिए भी कॉल करेंगे)।
यातायात
आपका रिसीवर ट्रैफ़िक पर विचार कर सकता है और उस समय ट्रैफ़िक के आधार पर उसके द्वारा संसाधित किए जाने वाले संदेशों की संख्या को समायोजित कर सकता है। एक सरल दृष्टिकोण यह होगा कि पिछले ट्रैफ़िक डेटा के आधार पर आपके उच्च ट्रैफ़िक घंटों की भविष्यवाणी की जाए और मान लिया जाए कि आप एक क्रोन स्क्रिप्ट के साथ गए हैं जो हर x
मिनट आपको कुछ इस तरह से चलता है :
if(
now() > 2pm && now() < 7pm
) {
process(10);
} else {
process(100);
}
function process(count) {
for(i=0; i<=count; i++) {
message = dequeue();
mail(message)
}
}
एक बहुत ही भोला और गंदा दृष्टिकोण, लेकिन यह काम करता है। यदि यह ठीक नहीं है, तो दूसरा तरीका यह होगा कि प्रत्येक सर्वर पर आपके सर्वर के वर्तमान ट्रैफ़िक का पता लगाया जाए और उसके अनुसार प्रक्रिया की संख्या को समायोजित किया जाए। कृपया माइक्रो-ऑप्टिमाइज़ न करें यदि यह बिल्कुल आवश्यक नहीं है, तो आप अपना समय बर्बाद कर रहे हैं।
कतार भंडारण
यदि आपका एप्लिकेशन पहले से ही एक डेटाबेस का उपयोग करता है, तो उस पर एक एकल तालिका सबसे सरल समाधान होगी:
CREATE TABLE message_queue (
id int(11) NOT NULL AUTO_INCREMENT,
timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
processed enum('0','1') NOT NULL DEFAULT '0',
message varchar(255) NOT NULL,
PRIMARY KEY (id),
KEY timestamp (timestamp),
KEY processed (processed)
)
यह वास्तव में उससे अधिक जटिल नहीं है। आप निश्चित रूप से इसे आवश्यकतानुसार जटिल बना सकते हैं, उदाहरण के लिए, आप एक प्राथमिकता फ़ील्ड जोड़ सकते हैं (जिसका अर्थ होगा कि यह अब फीफो कतार नहीं है, लेकिन अगर आपको वास्तव में इसकी आवश्यकता है, तो कौन परवाह करता है?)। आप इसे संसाधित क्षेत्र को छोड़ कर (लेकिन फिर आपको उन्हें संसाधित करने के बाद पंक्तियों को हटाना होगा) को भी सरल बना सकते हैं।
एक डेटाबेस तालिका प्रति दिन 2000 संदेशों के लिए आदर्श होगी, लेकिन यह संभवतः प्रति दिन लाखों संदेशों के लिए अच्छी तरह से पैमाने पर नहीं होगी । विचार करने के लिए एक लाख कारक हैं, आपके बुनियादी ढांचे में सब कुछ आपके आवेदन की समग्र मापनीयता में एक भूमिका निभाता है।
किसी भी स्थिति में, आपने पहले ही डेटाबेस आधारित कतार को एक अड़चन के रूप में पहचान लिया है, अगला कदम क्लाउड सेवा पर एक नज़र रखना होगा। अमेज़ॅन SQS एक सेवा है जिसका मैंने उपयोग किया था, और उसने जो वादा किया था, वह किया। मुझे यकीन है कि वहाँ कुछ समान सेवाएँ हैं।
मेमोरी आधारित कतारें भी विचार करने के लिए कुछ है, विशेष रूप से अल्पकालिक कतारों के लिए। memcached संदेश कतार भंडारण के रूप में उत्कृष्ट है।
जो भी भंडारण आप अपनी कतार बनाने का निर्णय लेते हैं, वह स्मार्ट और सार है। न तो आपके प्रेषक और न ही आपके रिसीवर को एक विशिष्ट भंडारण से जोड़ा जाना चाहिए, अन्यथा बाद के समय में एक अलग भंडारण पर स्विच करना एक पूर्ण पीटा होगा।
वास्तविक जीवन दृष्टिकोण
मैंने ईमेल के लिए एक संदेश कतार बनाई है जो आपके द्वारा किए जा रहे कार्यों के समान है। यह एक PHP प्रोजेक्ट पर था और मैंने इसे Zend Queue के आसपास बनाया है , Zend फ्रेमवर्क का एक घटक है जो विभिन्न चरणों के लिए कई एडेप्टर प्रदान करता है । मेरा भंडारण कहाँ:
- इकाई परीक्षण के लिए PHP सरणियाँ,
- उत्पादन पर अमेज़न SQS,
- MySQL देव और परीक्षण वातावरण पर।
मेरे संदेश उतने ही सरल थे जितना वे हो सकते हैं, मेरे आवेदन ने आवश्यक जानकारी ( [user_id, reason]
) के साथ छोटे सरणियों का निर्माण किया । संदेश भंडार उस सरणी का क्रमबद्ध संस्करण था (पहले यह PHP का आंतरिक क्रमांकन प्रारूप था, फिर JSON, मुझे याद नहीं है कि मैंने स्विच क्यों किया था)। reason
एक निरंतर है और निश्चित रूप से मैं एक बड़ी मेज कहीं कि नक्शे है reason
संपूर्ण स्पष्टीकरण के लिए (मैं गुप्त के साथ ग्राहकों को ईमेल 500 के बारे में भेजने के लिए प्रबंधन कैसे किया reason
बजाय एक बार संपूर्ण संदेश)।
आगे की पढाई
मानक:
उपकरण:
दिलचस्प पढ़ता है: