消息中间件之ActiveMQ学习笔记

目录

  • JMS介绍
  • ActiveMQ简介及安装
  • ActiveMQ的实例
  • ActiveMQ配置介绍
  • ActiveMQ的部署模式
  • ActiveMQ与Spring整合实例

JMS介绍

  1. 基本概念
    JMS(Java Service Message)即Java消息服务应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
  2. 对象模型
    (1)连接工厂(ConnectionFactory)是由管理员创建,并绑定到JNDI树中。客户端使用JNDI查找连接工厂,然后利用连接工厂创建一个JMS连接。
    (2)JMS连接(Connection)表示JMS客户端和服务器端之间的一个活动的连接,是由客户端通过调用连接工厂的方法建立的。
    (3)JMS会话(Session)表示JMS客户与JMS服务器之间的会话状态。JMS会话建立在JMS连接上,表示客户与服务器之间的一个会话线程。
    (4)JMS目的(Destination),又称为消息队列,是实际的消息源。
    (5)生产者(Message Producer)和消费者(Message Consumer)对象由Session对象创建,用于发送和接收消息。
    (6)监听器(MessageListener),如果注册了消息监听器,一旦消息到达,将自动调用监听器的onMessage方法。
  3. 消息模型
    (1)点对点(Point-to-Point)
    在点对点的消息系统中,消息分发给一个单独的使用者。发送者和接收者之间在时间上没有依赖性,接收者在成功接收消息之后需向队列应答成功,点对点消息往往与队列(javax.jms.Queue)相关联。


    消息中间件之ActiveMQ学习笔记_第1张图片
    image_1chgenqc1a0h5nffto1dqu1lio9.png-42kB

    (2)发布/订阅(Publish/Subscribe)
    发布/订阅消息系统支持一个事件驱动模型,消息生产者和消费者都参与消息的传递。生产者发布事件,而使用者订阅感兴趣的事件,并使用事件。发布者和订阅者之间有时间上的依赖性。该类型消息一般与特定的主题(javax.jms.Topic)关联。


    消息中间件之ActiveMQ学习笔记_第2张图片
    image_1chgesjdb1cj19611m731dqbvv513.png-52.3kB
  4. 基本组件
    (1)Broker:消息代理。表示消息队里服务器实体
    (2)Producer:消息生产者。业务发起方
    (3)Consumer:消息消费者。业务处理方
    (4)Topic:主题。在发布/订阅模式下消息的统一汇集地
    (5)Queue:队列。在点对点模式下,特定生产者向特定队列发送消息
    (6)Message:消息。根据不同的通信协议定义的固定格式进行编码的数据包

ActiveMQ简介及安装

  1. 简介
    ActiveMQ是由Apache出品的,一款最流行的,能力强劲的开源消息中间件。ActiveMQ是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,它非常快速,支持多种语言的客户端和协议,而且可以非常容易的嵌入到企业的应用环境中,并有许多高级功能。
  2. 安装使用
    (1)官网下载地址ActiveMQ
    (2)运行服务
    解压后找到脚本目录
    消息中间件之ActiveMQ学习笔记_第3张图片
    image_1chgf6dmo1kh1cnim1oqaa1m3u1g.png-58kB

    执行./activemq start命令,出现Starting ActiveMQ Broker...即成功启动
    image_1chgf7mhn18cc1hta1efamv886l1t.png-9.9kB
    image_1chgf7mhn18cc1hta1efamv886l1t.png-9.9kB

    访问默认页面,地址http://127.0.0.1:8161/admin/
    默认页面访问端口是8161
    默认用户和密码都是admin
    消息中间件之ActiveMQ学习笔记_第4张图片
    image_1chgfc3vv1dueo7v16h31ptokf52a.png-161.2kB
  3. 特性介绍
    (1)多种语言和协议编写客户端。语言: Java, C, C++, C#, Ruby, Perl, Python, PHP。应用协议: OpenWire,STOMP REST,MQTT,AMQP
    (2)完全支持JMS1.1和J2EE 1.4规范 (持久化,分布式事务消息,事务)
    (3)对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的框架中去
    (4)连接模式多样化,支持多种传输协议:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA
    (5)支持通过JDBC和journal提供快速的消息持久化
    (6)为高性能集群,客户端-服务器,点对点通信场景而设计
    (7)可以轻松地与CXF、Axis等Web Service技术整合
    (8)可以被作为内存中的JMS提供者,非常适合JMS单元测试
    (9)提供了REST API接口
    (10)支持以AJAX方式调用
  4. 使用场景
    (1)多个项目之间集成,跨平台 ,多语言
    (2)降低系统间模块的耦合度,解耦
    (3)系统前后端隔离

ActiveMQ的简单实例

  • 点对点模式
public static void main(String[] args) {
        //1.创建工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_USER,ActiveMQConnectionFactory.DEFAULT_PASSWORD,ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL);
        Connection connection = null;
        Session session = null;
        try {
            //2.创建连接
            connection = connectionFactory.createConnection();
            connection.start();
            //3.创建session
            //Session.AUTO_ACKNOWLEDGE: 接收到消息时,自动ack确认消息 
            //Session.CLIENT_ACKNOWLEDGE:接收到消息时,客户端调用message.acknowledge(),显式对消息确认。
            session = connection.createSession(Boolean.FALSE,Session.AUTO_ACKNOWLEDGE);
            //4.创建Destination
            Destination destination = session.createQueue("hello");
            //5.创建生产者/消费者
            MessageProducer messageProducer = session.createProducer(destination);
            MessageConsumer messageConsumer = session.createConsumer(destination);
            //6.设置持久化方式
            messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            //7.定义消息对象并发送/接受
            TextMessage textMessage = session.createTextMessage();
            textMessage.setText("helloworld");
            messageProducer.send(textMessage);
            TextMessage receiveMessage = (TextMessage) messageConsumer.receive();
            System.out.println(receiveMessage.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }finally {
            if(connection!=null){
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
            if(session!=null){
                try {
                    session.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }
点对点

Messages Enqueued:表示生产了多少条消息,记做P
Messages Dequeued:表示消费了多少条消息,记做C
Number Of Consumers:表示在该队列上还有多少消费者在等待接受消息
Number Of Pending Messages:表示还有多少条消息没有被消费,实际上是表示消息的积压程度,就是P-C

  • 发布订阅模式
public class TestPublish {
    private static final String TOPIC  = "TestPublish.";
    private static final String[] topics = {"A", "B", "C"};
    public static void main(String[] args) {
        Publisher publisher = new Publisher();
        publisher.setTopics(topics);
        for (int i = 0; i < 10; i++) {
            publisher.sendMessage(topics);
        }
        publisher.close();

    }
    public static class Listener implements MessageListener {
        @Override
        public void onMessage(Message message) {
            try {
                MapMessage map = (MapMessage)message;
                String msg = map.getString("msg");
                double version = map.getDouble("version");
                System.out.println(msg+" version is "+version);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
    public static class Customer{
        public static void main(String[] args) {
            Customer customer = new Customer();
            try {
                for (String topic : topics) {
                    Destination destination = customer.getSession().createTopic(TOPIC + topic);
                    MessageConsumer messageConsumer = customer.getSession().createConsumer(destination);
                    messageConsumer.setMessageListener(new Listener());
                }
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
        private Connection connection = null;
        private Session session;
        public Customer() {
            ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_USER, ActiveMQConnectionFactory.DEFAULT_PASSWORD, ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL);
            try {
                connection = connectionFactory.createConnection();
                connection.start();
                session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }

        public Session getSession() {
            return session;
        }
    }
    public static class Publisher {
        private Connection connection = null;
        private Destination[] destinations;
        private Session session;
        private MessageProducer messageProducer;

        public Publisher() {
            ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_USER, ActiveMQConnectionFactory.DEFAULT_PASSWORD, ActiveMQConnectionFactory.DEFAULT_BROKER_BIND_URL);
            try {
                connection = connectionFactory.createConnection();
                connection.start();
                session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
                messageProducer = session.createProducer(null);
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }

        public void setTopics(String[] topics) {
            destinations = new Destination[topics.length];
            for (int i = 0; i < topics.length; i++) {
                try {
                    destinations[i] = session.createTopic(TOPIC + topics[i]);
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }

        private Message createTestMessage(String msg, Session session) {
            MapMessage message = null;
            try {
                message = session.createMapMessage();
                message.setString("msg", msg);
                message.setDouble("version", 1.00);
            } catch (JMSException e) {
                e.printStackTrace();
            }
            return message;
        }

        public void sendMessage(String[] msgs) {
            for (int i = 0; i < msgs.length; i++) {
                Message message = createTestMessage(msgs[i], session);
                try {
                    messageProducer.send(destinations[i], message);
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }

        public void close() {
            if (connection != null) {
                try {
                    connection.close();
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

ActiveMQ配置介绍

  • jetty-realm.properties
    该配置文件主要用于配置MQ登录页面的用户和密码
  • jetty.xml
    ActiveMQ内置jetty启动,该配置文件包含了管理功能的相关配置
  • activemq.xml
    该配置文件包含了很多主要功能的配置
    (1) 配置传输连接
    ActiveMQ提供了广泛的连接模式,包括HTTP/S、JGroups、JXTA、muticast、SSL、TCP、UDP、XMPP等,
    5.13.0+ 版本后,将OpenWire, STOMP, AMQP,MQTT这四种主要协议的端口监听进行了合并,并使用auto关键字进行表示。
    如果想给网络通信提供安全支持,则可以在uri中使用"auto+ssl"前缀
    如果想提高吞吐性,则可以在uri中使用"auto+nio"前缀

    
    
    
    
    
    

详细配置参考官网
除了这些基本协议之外,还支持一些高级协议

  1. Failover:一种重连机制,工作于上面介绍的连接协议之上,用于建立可靠的传输。配置语法:
    failover:(tcp://localhost/61616,tcp://remotehost:61616)?initialReconnectDelay=100
  2. Fanout:一种重连和复制机制,也是工作于其他连接协议之上, 采用复制的方式把消息复制到多台消息服务器上。配置语法:fanout:(tcp://localhost/61616,tcp://localhost:61617,tcp://localhost:61618)
    (2) 持久化存储模式
    AMQ消息存储—5.0及以前默认的消息存储,存放在Data Log中。

KahaDB消息存储—比AMQ消息存储更好的可扩展性和可恢复性—5.3以后推荐使用的消息存储


    

LevelDB消息存储—5.6以后推出的,使用自定义的索引代替了常用的BTree索引,性能高于KahaDB


    

JDBC消息存储—基于JDBC存储


    
    
    
    

       
    
     
     

Memory消息存储—基于内存的消息存储

 

(3)其他配置详细


    
      
        
        
          
          
            
              
              
          

          
          
            
              
            


          
           
            
                
           


          
          
            
            
          

          
          
            
            
            
          


          
          
            
             
          

          
          
            
             
          
          
          
            
               
          
        

        
        
             
                  
             
             
                
             
              
                   
             
            
                
            
            
                
            
           
                
           
           
                
                  
                      
                          
                      
                  
            
        
      
    

ActiveMQ的部署模式

  1. Master-Slave部署方式
    (1). Shared Filesystem Master-Slave方式
    支持N个AMQ实例组网,但由于他是基于kahadb存储策略,亦可以部署在分布式文件系统上,应用灵活、高效且安全。
    (2). Shared Database Master-Slave方式
    与shared filesystem方式类似,只是共享的存储介质由文件系统改成了数据库而已,支持N个AMQ实例组网,但他的性能会受限于数据库。
    (3). Replicated LevelDB Store方式
    ActiveMQ5.9以后才新增的特性,使用ZooKeeper协调选择一个node作为master。被选择的master broker node开启并接受客户端连接。其他node转入slave模式,连接master并同步他们的存储状态。slave不接受客户端连接。所有的存储操作都将被复制到连接至Master的slaves。如果master死了,得到了最新更新的slave被允许成为master。

  2. Broker-Cluster部署方式
    (1). Static Broker-Cluster部署
    (2). Dynamic Broker-Cluster部署

  3. 示例(基于Shared Filesystem Master-Slave方式):
    修改jetty.xml 和ActiveMQ.xml,保证在同一台机器上部署不会冲突,并创建共享文件夹,然后修改默认kahaDB配置



    
    



            


    


brokerURL="failover:(Master,Slave1,Slave2)?randomize=false"




   
     
   






    
     


 
    
 

ActiveMQ与Spring整合实例

pom.xml



    4.0.0

    springmvc
    springmvc
    1.0-SNAPSHOT
    war
    
        4.1.8.RELEASE
    

    
        
            junit
            junit
            4.10
            test
        


        
        
            jstl
            jstl
            1.2
        
        
            javax.servlet
            javax.servlet-api
            3.0.1
        
        
            commons-logging
            commons-logging
            1.1.1
        
        
            log4j
            log4j
            1.2.16
        
        
            org.slf4j
            slf4j-api
            1.7.7
        
        
            org.slf4j
            slf4j-log4j12
            1.7.7
        

        
        
            org.springframework
            spring-core
            ${springframework}
        
        
            org.springframework
            spring-context
            ${springframework}
        
        
            org.springframework
            spring-tx
            ${springframework}
        
        
            org.springframework
            spring-webmvc
            ${springframework}
        
        
            org.springframework
            spring-web
             ${springframework}
         
        
            org.springframework
            spring-aop
            ${springframework}
        
        
            org.springframework
            spring-test
            ${springframework}
            test
        
        
            org.springframework
            spring-jms
            ${springframework}
        

        
        
            org.apache.xbean
            xbean-spring
            4.6
        
        
         
            org.apache.activemq
             activemq-core
             5.7.0
         
        
            org.apache.activemq
            activemq-pool
            5.11.1
        
        
        
        
            org.apache.activemq
            activemq-web
            5.11.1
        
        
        
            commons-httpclient
            commons-httpclient
            3.1
        

    


applicationContext.xml



    
    
        
    
    

applicationContext-ActiveMQ.xml




     
                                           
    

    
    
        
        
    

    
    
        
        
            demotest
        
    
    
        
        
            chat1
        
    
    
    
        
        
        
        
        
    


    
    
    
    

    
    
          
        
        
        
    
    
    
        
        
        
    
    
        
        
        
    

spring-mvc.xml



    
    
        
    
    
        
        
    
    
    
        
        
        
        
    

web.xml



    springMvc
    
        /views/index.jsp
    
    
        default
        *.js
    
    
    
        org.apache.activemq.brokerURL
        tcp://localhost:61616
    
    
        AjaxServlet
        org.apache.activemq.web.AjaxServlet
        2
        true
    

    
        AjaxServlet
        /views/amq/*
    

    
    
        contextConfigLocation
        
            classpath:applicationContext*.xml;
        
    

    
        org.springframework.web.context.ContextLoaderListener
    

    
        springMVC
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            classpath:spring-mvc.xml
        
        1
        true
    
    
        springMVC
        /
    

    
    
        encodingFilter
        org.springframework.web.filter.CharacterEncodingFilter
        true
        
            encoding
            UTF-8
        
        
            forceEncoding
            true
        
    
    
        encodingFilter
        /*
    

部分代码

/**
 * @description:生产者
 * @author: micheal
 * @date:2018/7/8
 */
@Service("producerService")
public class ProducerService {
    @Resource
    private JmsTemplate jmsTemplate;

    public void sendMessage(final String msg){
        Destination destination = jmsTemplate.getDefaultDestination();
        System.out.println(Thread.currentThread().getName()+"向默认队列"+destination+"发送消息");
        jmsTemplate.send(session -> session.createTextMessage(msg));
    }
}
/**
 * @description:消费者
 * @author: micheal
 * @date:2018/7/8
 */
@Service("customerService")
public class CustomerService {
    @Resource
    private JmsTemplate jmsTemplate;

    public TextMessage receive(){
        Destination destination = jmsTemplate.getDefaultDestination();
        TextMessage textMessage = (TextMessage) jmsTemplate.receive(destination);
        return textMessage;
    }
}
/**
 * @author micheal
 */
public class TopicMessageListener implements MessageListener {
    @Override
    public void onMessage(Message message) {
        try {
            System.out.println("从队列:"+message.getJMSDestination()+"获取到消息:"+((TextMessage)message).getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

实现前端页面聊天室

<%--
  Created by IntelliJ IDEA.
  User: michael
  Date: 2018/7/10
  Time: 01:26
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
%>


    
    消息接受页面
   <%-- ActiveMQ的demo下有需要引入的js,复制过来即可--%>






发送 ajax JMS 消息

消息窗口


昵称:
消息:

参考链接

configuring-transports
Failover Transport
部署模式
成小胖学习ActiveMQ·基础篇
四种存储方式

你可能感兴趣的:(消息中间件之ActiveMQ学习笔记)