activeMQ消息队列连接池

来源:互联网 发布:js 固定长度数组 编辑:程序博客网 时间:2024/06/05 08:19
  • #activeMQ消息队列连接池创建实战
  • 适合了解MQ基本知识的同学
  • ## 为什么使用连接池 ##
  • 客户端发送请求的时候如果每次都创建Connection会消耗大量的资源,尤其是在高并发的情况下,服务器会被直接打死。试想北京到上海的铁路,如果每去一次就创建一条铁路是多么坑的事。不仅仅创建Connection会消耗资源,session、producer的创建也会消耗大量系统资源,所以针对这些资源都要相应的创建对应的连接池。
  • -

创建连接池

package com.swkj.pool;import com.swkj.commom.MessageType;import org.apache.activemq.ActiveMQConnection;import org.apache.activemq.ActiveMQConnectionFactory;import javax.jms.*;import java.util.LinkedList;/** * @author wangdongdong * @version V1.0 * @Description: AMQ连接池管理类 * @date 2017/10/25 0025 15:50 */public class AMQPoolFactory {    private static final String USERNAME = ActiveMQConnection.DEFAULT_USER;//默认连接用户名    private static final String PASSWORD = ActiveMQConnection.DEFAULT_PASSWORD;//默认连接密码    private static final String BROKEURL = ActiveMQConnection.DEFAULT_BROKER_URL; //默认连接地址    private int maxConnection = 10;  //connection最大连接数    private int minConnection = 1;    //connection最小连接数    private int maxSesstionConnection = 100; //每个connection可建的最大session数    private int minSesstionConnection = 10; //每个connection可建的最小session数    private int maxProducerSession = 10;    //每个session可建的最大producer数    private int maxConsumerSession = 10;   //每个session可建的最大consumer数    private ConnectionFactory factory;      //jms工厂    private LinkedList<ConnectionPool> poolConnection = new LinkedList<ConnectionPool>();    private LinkedList<SessionPool> poolSession = new LinkedList<SessionPool>();    /**     * 初始化AMQ连接池,生成连接和会话信息     *     * @throws Exception     */    private void initFactory() throws Exception {        try {            factory = new ActiveMQConnectionFactory(BROKEURL);            if (minConnection > 0 && minConnection <= maxConnection) {                for (int i = 0; i < minConnection; i++) {                    Connection connection = factory.createConnection(USERNAME, PASSWORD);                    connection.start();                    ConnectionPool connPool = new ConnectionPool();                    connPool.setConnection(connection);//存放Conn连接                    if (minSesstionConnection > 0 && minSesstionConnection <= maxSesstionConnection) {                        connPool.setActiveSessions(minSesstionConnection);//设置当前存在session数目                        for (int j = 0; j < minSesstionConnection; j++) {                            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);//为自动确认,pro con不用关心,由activemq确认信息是否到达。                            SessionPool sessionPool = new SessionPool();                            sessionPool.setConnection(connection);                            sessionPool.setSession(session);                            poolSession.addLast(sessionPool);                        }                        poolConnection.addLast(connPool);                    } else {                        throw new Exception("AMQ配置minSessionConnection和maxSessionConnection错误");                    }                }            } else {                throw new Exception("AMQ配置minConnections和maxConnections错误");            }        } catch (JMSException e) {            throw new Exception("AMQ初始化异常", e);        }    }    /**     * @author 王冬冬     * @Description: 从连接池中获取connection连接     * @date 2017/10/25 0025 16:21     * @version V1.0     */    private ConnectionPool getConnection() throws Exception {        ConnectionPool connPool = null;        if (poolConnection != null && poolConnection.size() > 0) {            for (ConnectionPool connectionPool : poolConnection) {                int poolSessionSize = connectionPool.getActiveSessions();                if (poolSessionSize < maxSesstionConnection) {                    connPool = connectionPool;//取会话比较少的连接                }            }            if (connPool == null && poolConnection.size() < maxConnection) {//当前连接池耗尽的时候需要新创建连接与会话                try {                    Connection conn = factory.createConnection(USERNAME, PASSWORD);                    conn.start();                    connPool = new ConnectionPool();                    connPool.setConnection(conn);//存放Conn连接                    if (minSesstionConnection > 0 && minSesstionConnection <= maxSesstionConnection) {                        connPool.setActiveSessions(minSesstionConnection);//设置当前存在session数目                        for (int j = 0; j < minSesstionConnection; j++) {                            Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);                            SessionPool sessionPool = new SessionPool();                            sessionPool.setSession(session);                            sessionPool.setConnection(conn);                            poolSession.addLast(sessionPool);                        }                    }                    poolConnection.addLast(connPool);                } catch (JMSException e) {                    throw new Exception("getConnection方法创建Connection异常", e);                }            }        }        return connPool;    }    /**     * @author 王冬冬     * @Description: 池中获取producer的session     * @date 2017/10/25 0025 16:32     * @version V1.0     */    private SessionPool getProducerSession() throws Exception {        SessionPool sesPool = null;        if (poolSession != null && poolSession.size() > 0) {            ConnectionPool connPool = getConnection();            for (SessionPool sessionPool : poolSession) {                if (sessionPool.getConnection() == connPool.getConnection()) {                    int poolProducerSize = sessionPool.getAvailableProducer();                    if (poolProducerSize < maxProducerSession) {                        sesPool = sessionPool;                    }                }            }            //会话占满的话,新建一个会话            if (sesPool == null && connPool.getActiveSessions() < maxSesstionConnection) {                try {                    Connection conn = connPool.getConnection();                    Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);                    sesPool = new SessionPool();                    sesPool.setConnection(conn);                    sesPool.setSession(session);                    poolSession.addLast(sesPool);                } catch (JMSException e) {                    throw new Exception("getProducerSession方法创建session出错", e);                }            }        }        return sesPool;    }    /**     * @author 王冬冬     * @Description: 池中获取consumer的session     * @date 2017/10/25 0025 16:43     * @version V1.0     */    private SessionPool getConsumerSession() throws Exception {        SessionPool sespool = null;        if (poolSession != null && poolSession.size() > 0) {            ConnectionPool connPool = getConnection();            for (SessionPool sessionPool : poolSession) {                if (sessionPool.getConnection() == connPool.getConnection()) {                    int poolConsumerSize = sessionPool.getAvailableConsumer();                    if (poolConsumerSize < maxConsumerSession) {                        sespool = sessionPool;                    }                }            }            //会话占满的话,新建一个会话            if (sespool == null && connPool.getActiveSessions() < maxSesstionConnection) {                try {                    Connection conn = connPool.getConnection();                    Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);                    sespool = new SessionPool();                    sespool.setConnection(conn);                    sespool.setSession(session);                    poolSession.addLast(sespool);                } catch (JMSException e) {                    throw new Exception("getConsumerSession方法创建session出错", e);                }            }        }        return sespool;    }    /**     * @author 王冬冬     * @Description: 获取producer连接     * @date 2017/10/25 0025 16:45     * @version V1.0     */    public ProducerPool getProducer(String name, String messageType) throws Exception {        SessionPool sessionPool = getProducerSession();        Session session = sessionPool.getSession();        try {            Destination ds = null;            if (messageType.equals(MessageType.Queue)) {                ds = session.createQueue(name);            }            if (messageType.equals(MessageType.Topic)) {                ds = session.createTopic(name);            }            MessageProducer producer = session.createProducer(ds);            ProducerPool producerPool = new ProducerPool();            producerPool.setProducer(producer);            producerPool.setConnection(sessionPool.getConnection());            producerPool.setSession(session);            producerIncreament(sessionPool);//producer增长1            return producerPool;        } catch (JMSException e) {            throw new Exception("获取Producer出错", e);        }    }    /**     * @author 王冬冬     * @Description: 获取consumer连接     * @date 2017/10/25 0025 16:51     * @version V1.0     */    public ConsumerPool getConsumer(String name, String messageType) throws Exception {        SessionPool sessionPool = getConsumerSession();        Session session = sessionPool.getSession();        try {            Destination ds = null;            if (messageType.equals(MessageType.Queue)) {                ds = session.createQueue(name);            }            if (messageType.equals(MessageType.Topic)) {                ds = session.createTopic(name);            }            MessageConsumer consumer = session.createConsumer(ds);            ConsumerPool consumerPool = new ConsumerPool();            consumerPool.setConnection(sessionPool.getConnection());            consumerPool.setSession(session);            consumerPool.setConsumer(consumer);            consumerIncreament(sessionPool);            return consumerPool;        } catch (JMSException e) {            throw new Exception("获取Consumer出错", e);        }    }    /**     * 池中可用producer递增1     *     * @param sessionPool     */    private void producerIncreament(SessionPool sessionPool) {        if (sessionPool != null) {            for (SessionPool sePool : poolSession) {                if (sePool == sessionPool) {                    int cnt = sePool.getAvailableProducer();                    cnt++;                    sePool.setAvailableProducer(cnt);                }            }        }    }    /**     * 池中可用producer递减1     *     * @param producerPool     */    public void producerDecreament(ProducerPool producerPool) {        if (producerPool != null) {            for (SessionPool sessionPool : poolSession) {                if (sessionPool.getConnection() == producerPool.getConnection()                        && sessionPool.getSession() == producerPool.getSession()) {                    int cnt = sessionPool.getAvailableProducer();                    cnt--;                    sessionPool.setAvailableProducer(cnt);                }            }        }    }    /**     * 池中可用consumer递增1     *     * @param sessionPool     */    private void consumerIncreament(SessionPool sessionPool) {        if (sessionPool != null) {            for (SessionPool sePool : poolSession) {                if (sePool == sessionPool) {                    int cnt = sePool.getAvailableConsumer();                    cnt++;                    sePool.setAvailableConsumer(cnt);                }            }        }    }    /**     * 池中可用consumer递减1     *     * @param consumerPool     */    public void consumerDecreament(ConsumerPool consumerPool) {        if (consumerPool != null) {            for (SessionPool sessionPool : poolSession) {                if (sessionPool.getConnection() == consumerPool.getConnection()                        && sessionPool.getSession() == consumerPool.getSession()) {                    int cnt = sessionPool.getAvailableConsumer();                    cnt--;                    sessionPool.setAvailableConsumer(cnt);                }            }        }    }    /**     * @author 王冬冬     * @Description:释放所有连接     * @date 2017/10/25 0025 16:53     * @version V1.0     */    public boolean disposeAll() throws Exception {        try {            if (poolSession != null && poolSession.size() > 0) {                for (SessionPool sessionPool : poolSession) {                    sessionPool.getSession().close();                }                poolSession.clear();            }            if (poolConnection != null && poolConnection.size() > 0) {                for (ConnectionPool connectionPool : poolConnection) {                    connectionPool.getConnection().stop();                    connectionPool.getConnection().close();                }                poolConnection.clear();            }            return true;        } catch (JMSException e) {            throw new Exception("释放连接出错", e);        }    }    /**     * @author 王冬冬     * @Description: 释放producer连接     * @date 2017/10/25 0025 16:53     * @version V1.0     */    public void disposeProducer(MessageProducer producer) throws Exception {        if (producer != null) {            try {                producer.close();            } catch (JMSException e) {                throw new Exception("释放producer连接出错", e);            }        }    }    /**     * @author 王冬冬     * @Description: 释放consumer连接     * @date 2017/10/25 0025 16:53     * @version V1.0     */    public void disposeConsumer(MessageConsumer consumer) throws Exception {        if (consumer != null) {            try {                consumer.close();            } catch (JMSException e) {                throw new Exception("释放consumer连接出错", e);            }        }    }}

生产者


package com.swkj.pro;import com.swkj.pool.AMQPoolFactory;import com.swkj.pool.ProducerPool;import javax.jms.MapMessage;import javax.jms.MessageProducer;import javax.jms.Session;import javax.jms.TextMessage;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.concurrent.locks.ReentrantLock;/*** @author 王冬冬* @Description: 生产者* @date 2017/10/25 0025 17:05* @version V1.0*/public class AMQProducer {    private ReentrantLock lock = new ReentrantLock();//互斥锁    /**    * @author 王冬冬    * @Description: 发送Map消息     *  @param dicMap map消息     * @param name 队列名称     * @param frequency 消息发送频率,多少条消息发送一次    * @date 2017/10/25 0025 17:23    * @version V1.0    */    public boolean sendMapMsg(AMQPoolFactory amqFactory, Map<String, Object> dicMap, String name, int frequency, String messageType)            throws Exception{        if (null == amqFactory){            throw new Exception("工厂为空");        }        if (dicMap.size() == 0) {            throw new Exception("消息为空");        }        if (null==name || "".equals(name)){            throw new Exception("队列名称不能为空");        }        //进入锁定状态        lock.lock();        List<String> keyList = new ArrayList<String>(dicMap.keySet());        boolean hasMsg = false;//是否还有剩余没法送消息标识        ProducerPool producerPool = amqFactory.getProducer(name,messageType);        Session session = producerPool.getSession();        MessageProducer producer = producerPool.getProducer();        try{            MapMessage mapMsg = session.createMapMessage();            for (int i = 0; i < keyList.size(); i++){                hasMsg = true;                mapMsg.setObject(keyList.get(i), dicMap.get(keyList.get(i)));                if ((i + 1) % frequency== 0){//4+1%5=0 五条一发                    producer.send(mapMsg);                    mapMsg.clearBody();                    hasMsg = false;                }            }            //取模后如果还有余数证明还有剩余得几条没有发送,所以应该发送干净            if(hasMsg){                producer.send(mapMsg);                mapMsg.clearBody();            }            return true;        }catch (Exception e){            amqFactory.disposeProducer(producer);            amqFactory.producerDecreament(producerPool);            throw new Exception("向队列发送数据异常", e);        }finally{            //用完释放            amqFactory.disposeProducer(producer);            amqFactory.producerDecreament(producerPool);            lock.unlock();        }    }    /**     * 发送文本消息     * @param amqFactory amq工厂实例     * @param text 文本消息     * @param name 目的地名称     */    public boolean sendTextMsg(AMQPoolFactory amqFactory, String text, String name,String messageType)            throws Exception{        if (null == amqFactory){            throw new Exception("工厂为空");        }        if (null == text || "".equals(text)) {            throw new Exception("发送内容不能为空");        }        if (null==name || "".equals(name)){            throw new Exception("队列名称不能为空");        }        //进入锁定状态        lock.lock();        ProducerPool producerPool = amqFactory.getProducer(name,messageType);        Session session = producerPool.getSession();        MessageProducer producer = producerPool.getProducer();        try{            TextMessage textMsg = session.createTextMessage();            textMsg.setText(text);            producer.send(textMsg);            return true;        }catch (Exception e){            amqFactory.disposeProducer(producer);            amqFactory.producerDecreament(producerPool);            throw new Exception("向队列发送数据异常", e);        }finally{                amqFactory.disposeProducer(producer);                amqFactory.producerDecreament(producerPool);            lock.unlock();        }    }}

消费者


package com.swkj.conn;import com.swkj.lister.ConsumerListener;import com.swkj.pool.AMQPoolFactory;import com.swkj.pool.ConsumerPool;import javax.jms.JMSException;import javax.jms.MessageConsumer;import javax.jms.MessageListener;import java.util.concurrent.locks.ReentrantLock;/*** @author 王冬冬* @Description: 消费者* @date 2017/10/26 0026 9:09* @version V1.0*/public class AMQReceiver {    private ReentrantLock lock = new ReentrantLock();//锁    /**    * @author 王冬冬    * @Description:设置自定义监听类    * @date 2017/10/26 0026 9:12    * @version V1.0    */    public boolean setListener(String name, AMQPoolFactory factory, Class<?> className, String messageType)            throws Exception{        if (null == factory) {            throw new Exception("工厂为空");        }        if (null == className) {            throw new Exception("监听类为空");        }        if (null == name || "".equals(name)) {            throw new Exception("队列名称不能为空");        }        //进入写模式锁定状态        lock.lock();        //反射机制实例化自定义监听类        ConsumerPool consumerPool = factory.getConsumer(name, messageType);        MessageConsumer consumer = null;        try {            ConsumerListener rece = (ConsumerListener)className.newInstance();            consumer = consumerPool.getConsumer();            consumer.setMessageListener(rece);            return true;        } catch (InstantiationException e) {            factory.disposeConsumer(consumer);            factory.consumerDecreament(consumerPool);            throw new Exception("监听类权限异常",e);        } catch (IllegalAccessException e) {                factory.disposeConsumer(consumer);                factory.consumerDecreament(consumerPool);                throw new Exception("实例化监听类异常",e);            } finally{            lock.unlock();        }    }}

自定义监听器
这块说下:使用了abstract抽象,把监听的onMessage默认实现了,
子类继承的时候,只需要处理业务逻辑就可以了,否则每个消费者都写一遍
onMessage没必要。


package com.swkj.lister;import org.apache.log4j.Logger;import javax.jms.*;import java.util.Enumeration;import java.util.HashMap;import java.util.Map;import static jdk.nashorn.internal.runtime.regexp.joni.Config.log;/** * @author 王冬冬 * @version V1.0 * @Description: 消息监听处理类,业务处理 * @date 2017/10/26 0026 9:20 */public abstract class ConsumerListener implements MessageListener {    private Logger log = Logger.getLogger(ConsumerListener.class);    public abstract void DealMap(Map<String, Object> dicMap);    public abstract void DealText(String text);    @Override    @SuppressWarnings("unchecked")    public void onMessage(Message message) {        try {            if (message instanceof MapMessage) {                MapMessage mapMsg = (MapMessage) message;                Map<String, Object> dicMap = new HashMap<String, Object>();                for (Enumeration<String> em = mapMsg.getMapNames(); em.hasMoreElements(); ) {                    String key = em.nextElement();                    dicMap.put(key, mapMsg.getObject(key));                }                // 调用子类接口                this.DealMap(dicMap);                return;            } else if (message instanceof TextMessage) {                TextMessage textMsg = (TextMessage) message;                String text;                text = textMsg.getText();                // 调用子类接口                this.DealText(text);                return;            }        } catch (JMSException e) {            log.error("接收数据异常", e.getCause());        }    }}

这块是子类处理信息
需要继承上面定义的监听类


package com.swkj.lister;import javax.jms.Message;import java.util.Map;/** * @author 王冬冬 * @version V1.0 * @Description: 具体业务处理 * @date 2017/10/26 0026 11:16 */public class BusinessImplementation extends ConsumerListener {    /**     * @author 王冬冬     * @Description: map类型信息处理     * @date 2017/10/26 0026 11:16     * @version V1.0     */    @Override    public void DealMap(Map<String, Object> dicMap) {        //写下你的业务逻辑    }    /**     * @author 王冬冬     * @Description: text类型信息处理     * @date 2017/10/26 0026 11:16     * @version V1.0     */    @Override    public void DealText(String text) {        //写下你的业务逻辑    }}

各种池对象
Connection池对象


package com.swkj.pool;import javax.jms.Connection;/** * @author 王冬冬 * @version V1.0 * @Description: Connection池对象 * @date 2017/10/25 0025 16:04 */public class ConnectionPool {    private Connection connection;    private int activeSessions;    public Connection getConnection() {        return connection;    }    public void setConnection(Connection connection) {        this.connection = connection;    }    public int getActiveSessions() {        return activeSessions;    }    public void setActiveSessions(int activeSessions) {        this.activeSessions = activeSessions;    }}

consumer池对象


package com.swkj.pool;import javax.jms.Connection;import javax.jms.MessageConsumer;import javax.jms.Session;/*** @author 王冬冬* @Description: consumer池对象* @date 2017/10/26 0026 11:41* @version V1.0*/public class ConsumerPool {    private Connection connection;    private Session session;    private MessageConsumer consumer;    public Connection getConnection() {        return connection;    }    public void setConnection(Connection connection) {        this.connection = connection;    }    public Session getSession() {        return session;    }    public void setSession(Session session) {        this.session = session;    }    public MessageConsumer getConsumer() {        return consumer;    }    public void setConsumer(MessageConsumer consumer) {        this.consumer = consumer;    }}

producer池对象


package com.swkj.pool;import javax.jms.Connection;import javax.jms.MessageProducer;import javax.jms.Session;/*** @author 王冬冬* @Description: producer池对象* @date 2017/10/26 0026 11:41* @version V1.0*/public class ProducerPool {    private Connection connection;    private Session session;    private MessageProducer producer;    public Connection getConnection() {        return connection;    }    public void setConnection(Connection connection) {        this.connection = connection;    }    public Session getSession() {        return session;    }    public void setSession(Session session) {        this.session = session;    }    public MessageProducer getProducer() {        return producer;    }    public void setProducer(MessageProducer producer) {        this.producer = producer;    }}

session池对象


package com.swkj.pool;import javax.jms.Connection;import javax.jms.Session;/** * @author wangdongdong * @version V1.0 * @Description: session池对象 * @date 2017/10/25 0025 16:08 */public class SessionPool {    private Connection connection;    private Session session;    private int availableProducer;    private int availableConsumer;    public Connection getConnection() {        return connection;    }    public void setConnection(Connection connection) {        this.connection = connection;    }    public Session getSession() {        return session;    }    public void setSession(Session session) {        this.session = session;    }    public int getAvailableProducer() {        return availableProducer;    }    public void setAvailableProducer(int availableProducer) {        this.availableProducer = availableProducer;    }    public int getAvailableConsumer() {        return availableConsumer;    }    public void setAvailableConsumer(int availableConsumer) {        this.availableConsumer = availableConsumer;    }}
原创粉丝点击