2009-10-29 5 views
7

में गतिशील रूप से एसिंक्रोनस संदेश कतार बनाने के लिए मुझे जावा में गतिशील रूप से एसिंक्रोनस संदेश कतार बनाने की आवश्यकता है। मेरा उपयोग केस एकाधिक एसएमटीपी सर्वरों के माध्यम से ईमेल भेज रहा है: मुझे यह लागू करने की आवश्यकता है कि एक ही एसएमटीपी सर्वर पर ईमेल अनुक्रमिक रूप से प्रक्रियाएं हों, लेकिन अलग-अलग एसएमटीपी सर्वरों के लिए ईमेल एक साथ संसाधित किया जा सकता है। मैंने अतीत में जेएमएस का उपयोग किया है, लेकिन जहां तक ​​मैं इसे देख सकता हूं केवल संकलन-समय कतार निर्माण की अनुमति देता है, जबकि मुझे रनटाइम पर कतार बनाने की आवश्यकता है (प्रत्येक SMTP सर्वर के लिए एक कतार)।जावा

क्या मुझे जेएमएस के बारे में कुछ याद आ रहा है या क्या कोई अन्य टूल/प्रस्ताव है जिसे मुझे देखना चाहिए?

+0

आप JMS विशेष रूप से उपयोग कर रहे हैं या है यह कुछ है कि आप java.util.concurrent और उसके ExecutorServices उपयोग कर सकते हैं करना है? –

+0

मैं विशेष रूप से जेएमएस का उपयोग नहीं कर रहा हूं, इसलिए मुझे एक्जिक्यूटर्स सर्विसेज पर एक नज़र डालेंगी, धन्यवाद। – Zecrates

उत्तर

6

मैं एडम से सहमत हूं, उपयोग केस लगता है जैसे जेएमएस ओवरहेड है। जावा में निर्मित कार्यक्षमता पर्याप्त:

package de.mhaller; 

import java.util.ArrayDeque; 
import java.util.ArrayList; 
import java.util.Deque; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.Queue; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.LinkedBlockingDeque; 

import org.junit.Assert; 
import org.junit.Test; 

public class Mailer { 

    @Test 
    public void testMailer() throws Exception { 
     ExecutorService executor = Executors.newCachedThreadPool(); 
     ArrayList<Mail> log = new ArrayList<Mail>(); 
     LinkedBlockingDeque<Mail> incoming = new LinkedBlockingDeque<Mail>(); 

     // TODO: Put mails to be sent into the incoming queue 
     incoming.offer(new Mail("[email protected]", "localhost")); 
     incoming.offer(new Mail("[email protected]", "otherhost")); 
     incoming.offer(new Mail("[email protected]", "otherhost")); 
     incoming.offer(new Mail("[email protected]", "localhost")); 

     Map<Mailserver, Queue<Mail>> queues = new HashMap<Mailserver, Queue<Mail>>(); 
     while (!incoming.isEmpty()) { 
      Mail mail = incoming.pollFirst(); 
      Mailserver mailserver = findMailserver(mail); 
      if (!queues.containsKey(mailserver)) { 
       ArrayDeque<Mail> serverQueue = new ArrayDeque<Mail>(); 
       queues.put(mailserver, serverQueue); 
       executor.execute(new SendMail(mailserver, serverQueue)); 
      } 
      Queue<Mail> slot = queues.get(mailserver); 
      slot.offer(mail); 
     } 

     assertMailSentWithCorrectServer(log); 
    } 

    private void assertMailSentWithCorrectServer(ArrayList<Mail> log) { 
     for (Mail mail : log) { 
      if (!mail.server.equals(mail.sentBy.mailserver)) { 
       Assert.fail("Mail sent by wrong server: " + mail); 
      } 
     } 
    } 

    private Mailserver findMailserver(Mail mail) { 
     // TODO: Your lookup logic which server to use 
     return new Mailserver(mail.server); 
    } 

    private static class Mail { 
     String recipient; 
     String server; 
     SendMail sentBy; 

     public Mail(String recipient, String server) { 
      this.recipient = recipient; 
      this.server = server; 
     } 

     @Override 
     public String toString() { 
      return "mail for " + recipient; 
     } 
    } 

    public static class SendMail implements Runnable { 

     private final Deque<Mail> queue; 
     private final Mailserver mailserver; 

     public SendMail(Mailserver mailserver, Deque<Mail> queue) { 
      this.mailserver = mailserver; 
      this.queue = queue; 
     } 

     @Override 
     public void run() { 
      while (!queue.isEmpty()) { 
       Mail mail = queue.pollFirst(); 
       // TODO: Use SMTP to send the mail via mailserver 
       System.out.println(this + " sent " + mail + " via " + mailserver); 
       mail.sentBy = this; 
      } 
     } 

    } 

    public static class Mailserver { 
     String hostname; 

     public Mailserver(String hostname) { 
      this.hostname = hostname; 
     } 

     @Override 
     public String toString() { 
      return hostname; 
     } 

     @Override 
     public int hashCode() { 
      return hostname.hashCode(); 
     } 

     @Override 
     public boolean equals(Object obj) { 
      return hostname.equals(((Mailserver) obj).hostname); 
     } 

    } 

} 
1

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

1

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

इस बात के आधार पर एक गंदे काम-आसपास के बारे में कि सभी समस्याओं को संकेत के अतिरिक्त स्तर से हल किया जा सकता है, जो मानता है कि उपलब्ध प्रिंटर का सेट तुलनात्मक रूप से छोटा है।

प्रिंटर 99 (या कुछ छोटी संख्या) के लिए कतार प्रिंटर 01 बनाएं। एक "डेटाबेस" है जो वास्तविक प्रिंटर के लिए कतार नक्शा करता है। प्रिंटर के अनुरोध के साथ आप मैपिंग टेबल में जोड़ सकते हैं। आपके पास कतारों को देखकर एमडीबी के कुछ ओवरहेड हो सकते हैं जिनका कभी भी उपयोग नहीं किया जाएगा, लेकिन जब तक कि आपके संभावित प्रिंटर की संख्या विशाल हो, तो आप इसे बर्दाश्त कर सकते हैं?

0

मैं ActiveMQ के साथ इस किया है अपने SMTP टूट सकते हैं और सीमा कतार उपभोक्ता (एमडीबी या संदेश श्रोता) से प्रत्येक के लिए एक कतार बनाएँ - मैं वास्तव में इस पर एक प्रश्न समय में, पोस्ट के रूप में मुझे इसी तरह की चिंताओं थी (उस समय जेएमएस दस्तावेज ने कहा था कि यह समर्थित नहीं था) और आश्वासन दिया गया था कि यह समर्थित था।

+0

क्या आपके पास अपने प्रश्न या दस्तावेज़ीकरण के लिए एक लिंक है जो यह प्राप्त करने का वर्णन करता है? – Zecrates