activeMQ生产者花了很长时间发送消息

时间:2014-10-06 11:06:37

标签: java activemq threadpool

我编写了一个生产者应用程序,它通过在activeMQ中使用Executer Service来排队JMS消息,并且它运行良好,但问题是需要很长时间才能将消息排入队列。

有三个文件: 1. ExecutePushServer.java 2. ActiveMQProducer.java 3. SendPush.java

ExecutePushServer.java:

package com.rh.pushserver;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;

public class ExecutePushServer {

/**
 * @uthor ankit
 */

static int maxThread = 0;
static BufferedReader br = null;
static String fileLocation = null;
static List<String> tokenList = new ArrayList<String>();
private static String txt;
static Properties configFile = new Properties();
private final static Logger logger = Logger
        .getLogger(ExecutePushServer.class.getName());

public static void main(String[] args) {
    // TODO Auto-generated method stub
    try {
        configFile.load(ExecutePushServer.class.getClassLoader()
                .getResourceAsStream("config.properties"));
        maxThread = Integer.valueOf(configFile.getProperty("POOL_SIZE"));

        fileLocation = configFile.getProperty("LOCATION");

        txt = configFile.getProperty("txt");
        logger.info("Message text is : " + txt);

        br = new BufferedReader(new FileReader(fileLocation));

        ActiveMQProducer mqProducer = new ActiveMQProducer();

        tokenList = getList(br);
        logger.info("tokenList created.");


        ExecutorService executor = Executors.newFixedThreadPool(maxThread);
        for (String id : tokenList) {
            Runnable work = new SendPush(mqProducer, id);
            executor.execute(work);
        }

        // This will make the executor accept no new threads
        // and finish all existing threads in the queue
        logger.info("All Ids Entered in Pool.");
        executor.shutdown();

        while (!executor.awaitTermination(10, TimeUnit.MINUTES)) {
            logger.info("Inside awaitTermination");
        }

        mqProducer.closeConnection();

    } catch (IOException e) {
        logger.error("Error in Reading File" + e);

    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        logger.error("Error in termination of executer" + e);
    } finally {
        try {
            if (br != null)
                br.close();

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

}

private static List<String> getList(BufferedReader br) {
    // TODO Auto-generated method stub
    String currentLine;
    try {
    while ((currentLine = br.readLine()) != null) {
        tokenList.add(currentLine);
    }

    return tokenList;

    } catch (IOException e) {
        logger.error("Error occured in creating tokenList !" + e);
        return null;
    } 
}

}

ActiveMQProducer.java

package com.rh.pushserver;


import java.io.IOException;
import java.util.Properties;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.MessageProducer;
import javax.jms.Session;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.log4j.Logger;

public class ActiveMQProducer {

/**
 * @uthor ankit  
 */


private final String url = ActiveMQConnection.DEFAULT_BROKER_URL;
private final String subject = "PUSH_NOTIFICATION";
private Connection connection;
private Session session;
private String txt=null;
private MessageProducer producer;
private MapMessage mapMessage;
static Properties configFile = new Properties();
private final static Logger logger=Logger.getLogger(ActiveMQProducer.class.getName());

public ActiveMQProducer() {
    try {
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
        connection = connectionFactory.createConnection();
        connection.start();

        logger.info("Connection Created.");

        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        Destination destination = session.createQueue(subject);
        producer = session.createProducer(destination);

        logger.info("Producer generated");

               configFile.load(ActiveMQProducer.class.getClassLoader().getResourceAsStream("config.properties"));

        txt=configFile.getProperty("txt");

        mapMessage = session.createMapMessage();
    } catch (JMSException e) {
        // TODO Auto-generated catch block
        logger.error("Error JMS Exception occured in creating connection"+e);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        logger.error("Exception occured while opening file "+e);
    }
}
public MessageProducer getProducer() {
    return producer;
}

public void enqueueMessage(String id){
    try {   
        mapMessage.setString("ID", id);
        mapMessage.setString("DISPLAY_STRING", txt);
        mapMessage.setInt("BADGE_COUNT", 1);
        mapMessage.setString("DEVICE_TYPE", "ANDROID");

        producer.send(mapMessage);
        logger.info("Sent on : "+id);

    } catch (JMSException e) {
        // TODO Auto-generated catch block
        logger.error("Error while Enqueue"+e);
    }
}

public void closeConnection(){
    try {
        connection.close();
        logger.info("Connection closed");
    } catch (JMSException e) {
        // TODO Auto-generated catch block
        logger.error("Error in connection closer"+e);
    }
}

}

SendPush.java

package com.rh.pushserver;



public class SendPush implements Runnable {
/**
 * @uthor ankit
 */

private String id;
private ActiveMQProducer mqProducer;


public SendPush(ActiveMQProducer mqProducer,String id) {

    this.id=id;
    this.mqProducer=mqProducer;
}

@Override
public void run() {

    mqProducer.enqueueMessage(id);
}

}

请帮助我!!

1 个答案:

答案 0 :(得分:0)

我要看的第一件事就是你的线程用法;你正在为每条消息创建一个新线程,这绝对是你的性能不快的原因之一。你为什么不能让你的线程运行一个发送消息的循环,直到它们用完要发送的消息为止,然后有N个线程分开工作?

您也可能希望在一个单独的线程中运行您的读取器逻辑,它会尽可能快地读取文件并将其读取的内容移交给线程,因此您不必等待文件被读取甚至开始。确保您创建用于在读取器线程之间传递数据的数据结构,并且消息线程是线程安全的!

一旦这样做,如果速度不是您想要的速度,请查看代理的配置。 (并在此处发布,如果您希望有人查看它。)特别是,如果您的消息是持久性的,那么请查看它们被持久化的位置,并查看是否还有其他更快的选项。 (JDBC存储通常是最慢的持久性选项,因此请考虑其他选项。)或者您甚至可以使您的消息非持久化以使其更快;你必须决定你是否可以接受这种权衡。弄清楚您的消息是异步传递还是同步传递;如果同步,则可能需要启用异步。并确保生产者流量控制没有进入(检查代理日志);如果是的话,那么你的消费者可能太慢了,并且正在减慢你的生产者。