वेब एप्लिकेशन और मोबाइल एप्लिकेशन के बैक-एंड को लागू करते समय, यहां तक कि सबसे सरल भी, यह इस तरह के टूल का उपयोग करने के लिए प्रथागत हो गया है: डेटाबेस, मेल (smtp) सर्वर, रेडिस सर्वर। उपयोग किए जाने वाले उपकरणों के सेट का लगातार विस्तार हो रहा है। उदाहरण के लिए, संदेश कतारें,
एमक्लिपिब पैकेज (प्रति सप्ताह 650 हजार इंस्टॉलेशन) की संख्या को देखते हुए, रिलेशनल डेटाबेस (प्रति सप्ताह mysql पैकेज 460 हजार इंस्टॉलेशन और प्रति सप्ताह 800 हजार इंस्टॉलेशन) के साथ सममूल्य पर उपयोग किया जाता है।
आज मैं नौकरी की कतारों के बारे में बात करना चाहता हूं, जो अब तक परिमाण के एक क्रम का कम उपयोग किया जाता है, हालांकि उनके लिए आवश्यकता लगभग सभी वास्तविक परियोजनाओं में पैदा होती है
तो, नौकरी की कतारें आपको कुछ कार्य असिंक्रोनस रूप से करने की अनुमति देती हैं, वास्तव में, दिए गए इनपुट मापदंडों के साथ और निर्धारित समय पर एक कार्य करते हैं।
मापदंडों के आधार पर, कार्य किया जा सकता है:
- नौकरियों की कतार में जोड़ने के तुरंत बाद;
- एक बार निर्धारित समय पर;
- कई बार तय समय पर।
नौकरी की कतारें आपको उस नौकरी में मापदंडों को स्थानांतरित करने की अनुमति देती हैं जो विफल हो रही हैं, ट्रैक करें और फिर से चलाएं जाने वाली नौकरियां, और एक साथ चलने वाली नौकरियों की संख्या पर एक सीमा निर्धारित करें।
Node.js पर अधिकांश एप्लिकेशन वेब और मोबाइल एप्लिकेशन के लिए REST-API के विकास से जुड़े हैं। एप्लिकेशन के साथ उपयोगकर्ता के आरामदायक काम के लिए REST-API के निष्पादन समय को कम करना महत्वपूर्ण है। उसी समय, REST-API के लिए एक कॉल लंबा और / या संसाधन-गहन संचालन शुरू कर सकता है। उदाहरण के लिए, खरीदारी करने के बाद, आपको उपयोगकर्ता को मोबाइल एप्लिकेशन पर एक पुश संदेश भेजना होगा, या CRM REST-API पर खरीदारी करने के लिए अनुरोध भेजना होगा। इन प्रश्नों को अतुल्यकालिक रूप से किया जा सकता है। यदि आप नौकरी की कतारों में काम करने के लिए एक उपकरण नहीं रखते हैं तो यह सही कैसे करें? उदाहरण के लिए, आप संदेश कतार में एक संदेश भेज सकते हैं, एक कार्यकर्ता शुरू कर सकते हैं जो इन संदेशों को पढ़ेगा और इन संदेशों के आधार पर आवश्यक कार्य करेगा।
वास्तव में, यह नौकरी की कतार क्या है। हालांकि, यदि आप बारीकी से देखते हैं, तो नौकरी की कतारें संदेश कतार से कई बुनियादी अंतर हैं। सबसे पहले, संदेश (स्थिर) संदेश कतार में रखे जाते हैं, और नौकरी की कतार में किसी प्रकार का कार्य (फ़ंक्शन कॉल) शामिल होता है। दूसरे, नौकरी कतार में कुछ प्रोसेसर (कार्यकर्ता) की उपस्थिति का अर्थ है जो दिए गए कार्य को पूरा करेगा। इस मामले में, अतिरिक्त कार्यक्षमता की आवश्यकता है। बढ़े हुए लोड के मामले में प्रोसेसर प्रोसेसर की संख्या को पारदर्शी रूप से बढ़ाया जाना चाहिए। दूसरी ओर, एक प्रोसेसर-वर्कर पर एक साथ चल रहे कार्यों की संख्या को सीमित करना आवश्यक है ताकि पीक लोड को सुचारू किया जा सके और सेवा से इनकार किया जा सके। इससे पता चलता है कि एक ऐसे उपकरण की आवश्यकता है जो विभिन्न मापदंडों को निर्धारित करके अतुल्यकालिक कार्यों को चला सके, जितना कि REST-API का उपयोग करके अनुरोध करना आसान है (या यदि यह और भी आसान है तो बेहतर है)।
संदेश कतारों का उपयोग करते हुए, नौकरी की कतार के तुरंत बाद चलने वाली नौकरी की कतार को लागू करना अपेक्षाकृत सरल है। लेकिन अक्सर कार्य को एक निर्धारित समय पर या एक कार्यक्रम के अनुसार पूरा करना आवश्यक होता है। इन कार्यों के लिए, कई पैकेजों का व्यापक रूप से उपयोग किया जाता है जो लीनक्स में क्रोन लॉजिक को लागू करते हैं। निराधार नहीं होने के लिए, मैं कहूंगा कि नोड-क्रोन पैकेज में प्रति सप्ताह 480 हजार इंस्टॉलेशन, नोड-शेड्यूल - प्रति सप्ताह 170 हजार इंस्टॉलेशन हैं।
नोड-क्रोन का उपयोग करना, निश्चित रूप से, तपस्वी सेटइंटरवल () से अधिक सुविधाजनक है, लेकिन व्यक्तिगत रूप से, मुझे इसका उपयोग करते समय कई समस्याओं का सामना करना पड़ा है। यदि एक सामान्य दोष को व्यक्त करने के लिए, यह एक साथ निष्पादित कार्यों की संख्या पर नियंत्रण की कमी है (यह पीक लोड को उत्तेजित करता है: लोड बढ़ने से कार्यों का काम धीमा हो जाता है, कार्यों को धीमा करने से एक साथ निष्पादित कार्यों की संख्या बढ़ जाती है, जो सिस्टम को और भी अधिक लोड करता है), उत्पादकता बढ़ाने के लिए नोड चलाने की अक्षमता। -कई कोर पर (इस मामले में, सभी कार्यों को प्रत्येक कोर पर स्वतंत्र रूप से निष्पादित किया जाता है) और पूरा होने वाले कार्यों को ट्रैक करने और पुनः आरंभ करने के लिए उपकरणों की कमी। एक त्रुटि के साथ ज़िया।
मुझे आशा है कि मैंने दिखाया है कि इस तरह के उपकरण की आवश्यकता है क्योंकि डेटाबेस के रूप में ऐसे उपकरण के साथ काम कतार में है। और ऐसे फंड दिखाई दिए हैं, हालांकि वे अभी तक व्यापक रूप से उपयोग नहीं किए गए हैं। मैं उनमें से सबसे लोकप्रिय सूची देगा:
आज मैं बैल पैकेज के उपयोग पर विचार करूंगा, जो मैं खुद के साथ काम करता हूं। मैंने यह विशेष पैकेज क्यों चुना (हालांकि मैं अपनी पसंद दूसरों पर नहीं थोपता)। उस समय, जब मैंने संदेश कतार के सुविधाजनक कार्यान्वयन की तलाश शुरू की, मधुमक्खी-कतार परियोजना को पहले ही रोक दिया गया था। क्यू कार्यान्वयन, मधुमक्खी-कतार रिपॉजिटरी में दिए गए बेंचमार्क के अनुसार, अन्य कार्यान्वयन से काफी पीछे रह गया और, इसके अतिरिक्त, समय-समय पर निष्पादित कार्यों को चलाने के लिए साधन नहीं थे। एजेंडा परियोजना मोंगोडब डेटाबेस में भंडारण के साथ कतारों को लागू करता है। कुछ मामलों के लिए यह एक बड़ा प्लस है, अगर आपको कतार में कार्य करते समय सुपर-विश्वसनीयता की आवश्यकता होती है। हालांकि, न केवल यह एक निर्णायक कारक है। स्वाभाविक रूप से, मैंने लाइब्रेरी के सभी धीरज विकल्पों का परीक्षण किया, बड़ी संख्या में कतार में काम किया और फिर भी एजेंडे से निर्बाध काम नहीं मिल सका। जब कार्यों की एक निश्चित संख्या से अधिक हो जाती है, तो एजेंडा काम करना बंद कर देता है और काम करना बंद कर देता है।
इसलिए, मैं बैल पर बस गया, जो एक सुविधाजनक एपीआई को पर्याप्त गति और मापनीयता के साथ लागू करता है, क्योंकि बैल पैकेज बैकेंड के रूप में एक रेडिस सर्वर का उपयोग करता है। विशेष रूप से, आप रेडिस सर्वर के क्लस्टर का उपयोग कर सकते हैं।
कतार बनाते समय, नौकरी कतार के लिए इष्टतम मापदंडों का चयन करना बहुत महत्वपूर्ण है। कई पैरामीटर हैं, और उनमें से कुछ का मूल्य अभी मुझ तक नहीं पहुंचा है। कई प्रयोगों के बाद, मैं निम्नलिखित मापदंडों पर बस गया:
const Bull = require('bull'); const redis = { host: 'localhost', port: 6379, maxRetriesPerRequest: null, connectTimeout: 180000 }; const defaultJobOptions = { removeOnComplete: true, removeOnFail: false, }; const limiter = { max: 10000, duration: 1000, bounceBack: false, }; const settings = { lockDuration: 600000,
तुच्छ मामलों में, कई कतारें बनाने की आवश्यकता नहीं है, क्योंकि प्रत्येक कतार में आप विभिन्न कार्यों के लिए नाम निर्दिष्ट कर सकते हैं, और प्रत्येक नाम के साथ एक प्रोसेसर-कार्यकर्ता को जोड़ सकते हैं:
const { bull } = require('../bull'); bull.process('push:news', 1, `${__dirname}/push-news.js`); bull.process('push:status', 2, `${__dirname}/push-status.js`); ... bull.process('some:job', function(...args) { ... });
मैं उस अवसर का उपयोग करता हूं जो बैल पर जाता है "बॉक्स से बाहर" - कई कोर पर प्रोसेसर-श्रमिकों को समानांतर करने के लिए। ऐसा करने के लिए, दूसरा पैरामीटर कोर की संख्या निर्धारित करता है जिस पर प्रोसेसर-कार्यकर्ता लॉन्च किया जाएगा, और तीसरे पैरामीटर में फ़ाइल नाम नौकरी प्रसंस्करण कार्य की परिभाषा के साथ होगा। यदि ऐसी सुविधा की आवश्यकता नहीं है, तो आप दूसरे पैरामीटर के रूप में कॉलबैक फ़ंक्शन पास कर सकते हैं।
कार्य को ऐड () विधि के लिए एक कॉल द्वारा पंक्तिबद्ध किया जाता है, जिसमें मापदंडों में कतार नाम और ऑब्जेक्ट पास किए जाते हैं, जो बाद में कार्य हैंडलर को पारित किया जाएगा। उदाहरण के लिए, ORM हुक में, नई खबरों के साथ एक प्रविष्टि बनाने के बाद, मैं एसिंक्रोनस रूप से सभी ग्राहकों को एक पुश संदेश भेज सकता हूं:
afterCreate(instance) { bull.add('push:news', _.pick(instance, 'id', 'title', 'message'), options); }
ईवेंट हैंडलर टास्क ऑब्जेक्ट में पैरामीटर्स को ऐड () मेथड और दिए गए () फंक्शन के साथ स्वीकार करता है, जिसे टास्क पूरा होने की पुष्टि करने के लिए कॉल किया जाना चाहिए या यह सूचित करना चाहिए कि टास्क एक एरर के साथ समाप्त हो गया है:
const { firebase: { admin } } = require('../firebase'); const { makePayload } = require('./makePayload'); module.exports = (job, done) => { const { id, title, message } = job.data; const data = { id: String(id), type: 'news', }; const payloadRu = makePayload(title.ru, message.ru, data); const payloadEn = makePayload(title.en, message.en, data); return Promise.all([ admin.messaging().send({ ...payloadRu, condition: "'news' in topics && 'ru' in topics" }), admin.messaging().send({ ...payloadEn, condition: "'news' in topics && 'en' in topics" }), ]) .then(response => done(null, response)) .catch(done); };
नौकरी कतार की स्थिति देखने के लिए, आप अखाड़ा-बैल उपकरण का उपयोग कर सकते हैं:
const Arena = require('bull-arena'); const redis = { host: 'localhost', port: 6379, maxRetriesPerRequest: null, connectTimeout: 180000 }; const arena = Arena({ queues: [ { name: 'my_gueue', hostId: 'My Queue', redis, }, ], }, { basePath: '/', disableListen: true, }); module.exports = { arena };
और अंत में, थोड़ा जीवन हैक। जैसा कि मैंने कहा, बैल एक बैकेंड के रूप में एक रेडिस सर्वर का उपयोग करता है। रेडिस सर्वर को फिर से चालू करने की संभावना कम हो जाएगी। लेकिन इस तथ्य को जानते हुए कि सिस्टम प्रशासक कभी-कभी "मूली कैश को साफ़ कर सकते हैं", विशेष रूप से सभी कार्यों को हटाते समय, मैं मुख्य रूप से समय-समय पर चलने वाले कार्यों के बारे में चिंतित था, जो इस मामले में हमेशा के लिए बंद हो गए। इस संबंध में, मुझे ऐसे आवधिक कार्यों को फिर से शुरू करने का अवसर मिला:
const cron = '*/10 * * * * *'; const { bull } = require('./app/services/bull'); bull.getRepeatableJobs() .then(jobs => Promise.all(_.map(jobs, (job) => { const [name, cron] = job.key.split(/:{2,}/); return bull.removeRepeatable(name, { cron }); }))) .then(() => bull.add('check:status', {}, { priority: 1, repeat: { cron } })); setInterval(() => bull.add('check:status', {}, { priority: 1, repeat: { cron } }), 60000);
यही है, कार्य को पहले कतार से बाहर रखा गया है, और फिर फिर से सेट किया गया है, और यह सब (alas) setInterval () द्वारा। दरअसल, इस तरह के जीवन हैक के बिना, मैंने शायद बैल पर आवधिक कार्यों का उपयोग करने का फैसला नहीं किया होगा।
apapacy@gmail.com
3 जुलाई 2019