वेब एप्लिकेशन से भेजे गए स्वचालित ईमेल का प्रबंधन कैसे करें


12

मैं एक वेब एप्लिकेशन डिजाइन कर रहा हूं और मैं सोच रहा हूं कि स्वचालित ईमेल भेजने के प्रबंधन के लिए वास्तुकला को कैसे डिजाइन किया जाए।

वर्तमान में मेरे पास मेरे वेब ऐप में यह फीचर है और ईमेल उपयोगकर्ता इनपुट / इंटरैक्शन (जैसे एक नया उपयोगकर्ता बनाने) पर आधारित हैं। समस्या यह है कि मेल सर्वर से सीधे कनेक्ट होने में कुछ सेकंड लगते हैं। मेरे आवेदन को बढ़ाते हुए, यह भविष्य में एक महत्वपूर्ण बोतल गर्दन होगी।

मेरे सिस्टम आर्किटेक्चर के भीतर बड़ी मात्रा में स्वचालित ईमेल भेजने का प्रबंधन करने का सबसे अच्छा तरीका क्या है?

भेजे गए ईमेल की एक बड़ी राशि नहीं होगी (2000 एक दिन अधिकतम)। ईमेल को तुरंत भेजने की आवश्यकता नहीं है, 10 मिनट तक अंतराल ठीक है।

अद्यतन: संदेश कतारबद्ध उत्तर के रूप में दिया गया है, लेकिन इसे कैसे डिज़ाइन किया जाएगा? क्या इसे ऐप में संभाला जाएगा और एक शांत अवधि के दौरान संसाधित किया जाएगा, या क्या मुझे कतार का प्रबंधन करने के लिए एक नई 'मेल ऐप' या वेब सेवा बनाने की आवश्यकता है?


क्या आप हमें पैमाने का एक मोटा अर्थ दे सकते हैं? सैकड़ों, हजारों या लाखों मेल? इसके अलावा, क्या ईमेल तुरंत भेजा जाना चाहिए या एक छोटा अंतराल स्वीकार्य है?
यानिस

ईमेल भेजने में एक SMTP संदेश प्राप्त मेल होस्ट को सौंपना शामिल है, लेकिन इसका मतलब यह नहीं है कि संदेश वास्तव में वितरित किया गया है। इतनी प्रभावी रूप से, सभी ईमेल भेजने के लिए अतुल्यकालिक है, और "सफलता की प्रतीक्षा" करने का नाटक करने का कोई मतलब नहीं है।
किलियन फोथ

1
Im "सफलता की प्रतीक्षा नहीं कर रहा", लेकिन मुझे अपना अनुरोध स्वीकार करने के लिए smtp सर्वर का इंतजार करना होगा। @YannisRizos अपडेट देखें RE अपनी टिप्पणी
Gaz_Edge

2000 के लिए (जो आपके द्वारा वर्णित अधिकतम है) मेल यह सिर्फ काम करेगा। जब वे कहते हैं कि 10 व्यावसायिक घंटे यह प्रति मिनट 3 मेल है जो बहुत ही उल्लेखनीय है। बस यह सुनिश्चित करें कि आप अपने DNS रिकॉर्ड को अच्छी तरह से सेट करते हैं और प्रदाता आपको इन राशियों में भेजना स्वीकार करता है। इसके बारे में भी सोचें: "मेलस्वर क्या है?" 2000 मेल भेजने का भार चिंता की बात नहीं है।
ल्यूक फ्रेंकेन

जवाबों:


15

आम दृष्टिकोण, जैसा कि ओजस ने पहले ही उल्लेख किया है , एक संदेश कतार है । एक डिजाइन परिप्रेक्ष्य से एक संदेश कतार अनिवार्य रूप से एक FIFO कतार है , जो एक मौलिक डेटा प्रकार है:

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बजाय एक बार संपूर्ण संदेश)।

आगे की पढाई

मानक:

उपकरण:

दिलचस्प पढ़ता है:


वाह। बस सबसे अच्छा जवाब के बारे में मैं यहाँ पर कभी राहत मिली है! आप पर्याप्त धन्यवाद नहीं कर सकते!
गज़_एज

मैं, और यकीन है कि लाखों अन्य इस FIFO का उपयोग Gmail और Google Apps स्क्रिप्ट के साथ कर रहे हैं। Gmail फ़िल्टर किसी भी आने वाले मेल को मापदंड के आधार पर लेबल करता है, और सभी को, उन्हें कतार में रखता है। एक Google Apps स्क्रिप्ट हर X अवधि को चलाता है, पहले y संदेश प्राप्त करता है, उन्हें भेजता है, उन्हें हटाता है। कुल्ला और दोहराएँ।
डेवचन

6

आपको किसी प्रकार की कतार प्रणाली की आवश्यकता है।

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

ईमेल पर आपका महत्व हो सकता है ताकि कुछ पर तुरंत कार्रवाई हो (उदाहरण के लिए पासवर्ड रीसेट), और कम महत्व वाले लोगों को बाद में भेजे जाने के लिए बैच किया जा सके।


क्या आपके पास एक आर्किटेक्चर आरेख या उदाहरण है जो दिखाता है कि यह कैसे काम करता है? उदाहरण के लिए, क्या कतार एक अलग 'ऐप' कहती है मेल ऐप, या क्या यह एक शांत अवधि के दौरान वेब एप्लिकेशन के भीतर से प्रक्रिया प्राप्त करता है। या मुझे उन्हें संसाधित करने के लिए एक प्रकार की वेब सेवा बनानी चाहिए?
गाज_एडज

1
@ Gaz_Edge आपके एप्लिकेशन को कतार में आइटम पुश करता है। एक पृष्ठभूमि प्रक्रिया (एक क्रोन लिपि सबसे अधिक संभावना है) प्रत्येक n सेकंड में कतार से x आइटम पॉप करती है और उन्हें संसाधित करती है (आपके मामले में, ईमेल भेजता है)। एक एकल डेटाबेस तालिका छोटी मात्रा में वस्तुओं के लिए कतार भंडारण के रूप में ठीक काम करती है, लेकिन आम तौर पर एक डेटाबेस पर लेखन संचालन महंगा होता है और बड़ी मात्रा में आप अमेज़ॅन की एसक्यूएस जैसी सेवाओं को देखना चाहते हैं
यानिस

1
@ Gaz_Edge मुझे यकीन नहीं है कि मैंने जो भी लिखा है, उससे अधिक सरल आरेख कर सकता हूं "... एक डेटाबेस तालिका में लिखें और इस तालिका में एक और बाहरी अनुप्रयोग प्रक्रिया पंक्तियां हैं ...." और तालिका के लिए, "कोई भी कतार पढ़ें" "जो भी तकनीक हो सकती है।
ओज

1
(cont ...) आप उस पृष्ठभूमि प्रक्रिया का निर्माण कर सकते हैं जो कतार को इस तरह से साफ़ करती है जो आपके ट्रैफ़िक को ध्यान में रखती है, उदाहरण के लिए आप इसे कम आइटम (या बिल्कुल भी नहीं) संसाधित करने का निर्देश दे सकते हैं जब आपका सर्वर तनाव में हो। । आपको या तो अपने पिछले ट्रैफ़िक डेटा को देखने के द्वारा उन तनावपूर्ण समय की भविष्यवाणी करनी होगी (यह जितना आसान लगता है, लेकिन त्रुटि के एक बड़े मार्जिन के साथ है) या आपकी पृष्ठभूमि प्रक्रिया होने से हर बार ट्रैफ़िक स्थिति की जांच करें (अधिक सटीक, लेकिन जोड़ा उपरि शायद ही कभी आवश्यक है)।
यानि

@YannisRizos आपकी टिप्पणियों को एक उत्तर में जोड़ना चाहता है? इसके अलावा, आर्किटेक्चर आरेख और डिज़ाइन सहायक होंगे (मैं इस बार उन्हें इस प्रश्न से प्राप्त करने के लिए तैयार हूं
!;

2

भेजे गए ईमेल की एक बड़ी राशि नहीं होगी (2000 एक दिन अधिकतम)।

कतार के अलावा, दूसरी चीज जिस पर आपको विचार करना चाहिए, वह विशिष्ट सेवाओं के माध्यम से ईमेल भेज रही है: MailChimp, उदाहरण के लिए (मैं इस सेवा से संबद्ध नहीं हूं)। अन्यथा कई मेल-सेवाएँ, जैसे जीमेल, जल्द ही आपके पत्र एक स्पैम फ़ोल्डर में भेज देंगी।


2

मैंने अपनी कतार प्रणाली को अलग-अलग 2 तालिका में बनाया है;

CREATE TABLE [dbo].[wMessages](
  [Id] [uniqueidentifier]  NOT NULL,
  [FromAddress] [nvarchar](255) NOT NULL,
  [FromDisplayName] [nvarchar](255) NULL,
  [ToAddress] [nvarchar](255) NOT NULL,
  [ToDisplayName] [nvarchar](255) NULL,
  [Graph] [xml] NOT NULL,
  [Priority] [int] NOT NULL,
  PRIMARY KEY CLUSTERED ( [Id] ASC ))

CREATE TABLE [dbo].[wMessageStates](
  [MessageId] [uniqueidentifier] NOT NULL,
  [Status] [int] NOT NULL,
  [LastChange] [datetimeoffset](7) NOT NULL,
  [SendAfter] [datetimeoffset](7) NULL,
  [SendBefore] [datetimeoffset](7) NULL,
  [DeleteAfter] [datetimeoffset](7) NULL,
  [SendDate] [datetimeoffset](7) NULL,
  PRIMARY KEY CLUSTERED ( [MessageId] ASC )) ON [PRIMARY]
) ON [PRIMARY]

इन तालिकाओं के बीच 1-1 संबंध है।

संदेश सामग्री को संग्रहीत करने के लिए संदेश तालिका। वास्तविक सामग्री (To, CC, BCC, विषय, निकाय आदि) को XML प्रारूप में ग्राफ क्षेत्र में क्रमबद्ध किया जाता है। अन्य से, सूचना के लिए, बिना डिस्क्राइलाइज़िंग ग्राफ़ के मुद्दों की रिपोर्टिंग के लिए उपयोग किया जाता है। इस तालिका को अलग करने से तालिका सामग्री को एक अलग डिस्क भंडारण में विभाजित करने की अनुमति मिलती है। एक बार जब आप एक संदेश भेजने के लिए तैयार हो जाते हैं तो आपको सभी जानकारी पढ़ने की आवश्यकता होती है इसलिए प्राथमिक कुंजी सूचकांक के साथ एक कॉलम में सभी सामग्री को क्रमबद्ध करने के साथ कुछ भी गलत नहीं है।

अतिरिक्त दिनांक आधारित जानकारी के साथ संदेश सामग्री के भंडारण की स्थिति के लिए MessageState तालिका। इस तालिका को अलग करने से तेजी से आईओ भंडारण पर अतिरिक्त अनुक्रमित के साथ तेजी से तंत्र का उपयोग करने की अनुमति मिलती है। अन्य कॉलम पहले से ही आत्म व्याख्यात्मक हैं।

आप एक अलग थ्रेड पूल का उपयोग कर सकते हैं जो इस तालिकाओं को स्कैन करता है। यदि एप्लिकेशन और पूल एक ही मशीन में रहते हैं, तो आप इन तालिकाओं में डाली गई किसी चीज़ के बारे में आवेदन से पूल को संकेत करने के लिए EventWaitHandle वर्ग का उपयोग कर सकते हैं , अन्यथा समय-समय पर स्कैन करना सबसे अच्छा है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.