ActiveMQ——1、JMS简介与ActiveMQ入门

1.背景&JMS概述

当前CORBA、DCOM、RMI等RPC中间件技术已广泛应用于各个领域。但是面对规模和复杂度都越来越高的分布式系统,这些技术也显示出其局限性:

(1)同步通信:客户端发出调用后,必须等待服务对象完成处理并返回结果后才能继续执行;

(2)客户端和服务对象的生命周期紧密耦合:客户进程和服务对象进程都必须正常运行,如果由于服务对象崩溃或者网络故障导致客户的请求不可达,客户端会收到异常;

(3)点对点通信:客户端的一次调用只发送给某个单独的目标对象。

面向消息的中间件(Message Oriented Middleware,MOM)较好的解决了以上问题。发送者将消息发送给消息服务器,消息服务器将消息存放在若干队列中,在合适的时候再将消息发送给接收者。这种模式下,发送和接收是异步的,发送者无需等待;二者的生命周期未必相同:发送消息的时候接收者不一定运行,接收消息的时候发送者也不一定运行;一对多通信:一个消息可以有多个接收者。

JAVA消息服务(JMS)定义了JAVA中访问消息中间件的接口。JMS只是接口,并没有给予实现,实现JMS接口的消息中间件称为JMS Provider,已有的MOM系统包括Apache的ActiveMQ、以及阿里巴巴的RocketMQ、IBM的MQSeries、Microsoft的MSMQ和BEA的MessageQ、RabbitMQ等等,他们基本都遵循JMS规范。

2.JMS术语

Provider(MessageProvider):生产者

由会话创建的对象,用于发送消息到目标。用户可以创建某个目标的发送者,也可以创建一个通用的发送者,在发送时指定目标。

Consumer(MessageConsumer):消费者

由会话创建的对象,用于接收发送到目标的消息。消费者可以同步的(阻塞模式)或异步的(非阻塞模式)接收队列或主题类型的消息。

PTP(Point to Point):点对点消息模型

Pub/Sub(Publish/Subscribe):发布/订阅消息模型

Queue:队列目标

Topic:主题目标

ConnectionFactory:连接工厂,JMS用它创建连接

用户用来创建到JMS提供者的连接的被管对象。JMS客户端通过可移植的接口访问连接,这样当下层的实现改变时,客户端代码不需要进行修改。管理员需要在JNDI命名空间中配置连接工厂,这样JMS客户端才能查找到他们。根据消息类型的不同,用户可以使用队列连接工厂或主题连接工厂。

Connection:JMS客户端到JMS Provider的连接

连接代表了应用程序和消息服务器之间的通信链路。在获得连接工厂后,就可以创建一个与JMS提供者通信的连接。根据不同的连接类型,连接允许用户创建会话,以发送和接收队列和主题到目标。

Destination:消息的目的地

目标是一个包装了消息目标标识符的被管对象,消息目标是指消息发布和接收的地点,可以是队列或主题。JMS管理员创建这些对象,然后用户通过JNDI发现它们。和连接工厂一样,管理员可以创建两种类型的消息目标:点对点模型的队列以及发布者/订阅者模型的主题。

Session:会话,一个发送或接收消息的线程

表示一个单线程的上下文,用于发送和接收消息。由于会话是单线程的,所以消息是连续的,就是说消息是按照发送的顺序一个一个接收的。会话的好处是支持事务,如果用户选择了事务支持,会话上下文将保存一组消息,直到事务被提交才发送这些消息。在提交事务之前,用户可以使用回滚操作来取消这些消息。会话允许用户创建消息生产者来发送消息,创建消息消费者来接收消息。

Message:消息

在消费者和生产者之间传递的对象,也就是说从一个应用程序创建并发送到另一个应用程序。一个消息有三个主要部分:

①消息头(必须):包含用于识别和为消息寻找路由的操作设置。

②一组消息属性(可选):包含额外的属性,支持其他提供者和用户的兼容。可以创建定制的字段和过滤器(消息选择器)。

③一个消息体(可选):允许用户创建五种类型的消息,文本消息、映射消息、字节消息、流消息和对象消息。

3.消息格式定义

JMS定义了五种不同的消息正文格式,以及调用的消息类型,允许发送并接收一些不同形式的数据,提供现有消息格式的一些级别的兼容性。

①StreamMessage:JAVA原始值的数据流

②MapMessage:套key-value对

③TextMessage:字符串对象

④ObjectMessage:序列化的Java对象

⑤BytesMessage:字节数组对象

4.ActiveMQ简介

ActiveMQ是Apache出品,最流行的,能力强大的开源消息总线。ActiveMQ是一个完全支持JMS 1.1和J2EE 1.4规范的JMS Provider实现,尽管JMS规范出台已经很久了,但JMS在当今的JAVAEE应用中仍然扮演着特殊的地位,可以说ActiveMQ在业界应用最广泛,当然如果想要有更强大的性能和海量数据处理能力,ActiveMQ还需要不断的升级版。80%以上的业务使用ActiveMQ已经足够满足需求,当然后续如天猫、淘宝这种大型的电商网站,尤其是双11这种特殊时期,ActiveMQ需要进行很复杂的优化源码以及架构设计才能完成,ActiveMQ是阿里巴巴的RocketMQ的核心,所以必须要掌握好ActiveMQ。

5.安装ActiveMQ

到ActiveMQ官网下载Linux版本的压缩包,我这里使用的是5.14.3。

tar -zxvf apache-activemq-5.14.3-bin.tar.gz,解压ActiveMQ压缩包。

cd apache-activemq-5.14.3/bin,进入ActiveMQ的bin目录

./activemq start,启动ActiveMQ

在浏览器中输入192.168.1.102:8161(你自己安装ActiveMQ机器的ip,8161是ActiveMQ的默认端口号,用户名和密码默认都为admin)打开ActiveMQ管控台,界面如下:


6.使用Java操作ActiveMQ(HelloWorld入门)

Producer(生产者):

public class Producer {
    public static void main(String[] args) throws JMSException {
        //1.建立ConnectionFactory工厂对象,需要填入用户名、密码以及ActiveMQ地址,默认端口为tcp://localhost:61616
        ConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_USER,
                ActiveMQConnectionFactory.DEFAULT_PASSWORD, "tcp://192.168.1.104:61616");
        //2.通过ConnectionFactory工厂对象创建Connection连接,并调用Connection对象的start方法开启连接,默认为关闭状态
        Connection connection = factory.createConnection();
        //3.通过Connection对象创建Session会话(上下文环境对象),用于接收和发送消息,参数一:是否开启事务,参数二:签收模式,一般设置为自动签收
        Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
        //4.通过Session对象创建Destination对象,用来指定生产消息和消费消息来源的对象,在PTP中,Destination被称为Queue(队列),
        //在Publish/Subscribe模式,Destination被称为Topic(主题)。程序中可以有多个Queue和Topic。
        Destination destination = session.createQueue("queue1");
        //5.通过Session对象创建消息的发送和接收对象(生产者和消费者)MessageProducer和MessageConsumer
        MessageProducer producer = session.createProducer(destination);
        //6.使用MessageProducer的setDeliveryMode方法设置持久化特性或非持久化。
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
        //7.使用JMS规范的TextMessage形式创建数据(通过Session对象创建),并用MessageProducer的send方法发送数据。客户端使用receive方法接收数据
        TextMessage message = new ActiveMQTextMessage();
        for(int i=0; i<5; i++) {
            message.setText("消息:" + i);
            producer.send(destination, message);
        }
        //8.关闭Connection
        if(connection != null) {
            connection.close();
        }
    }
}
每一行代码都有注释,我在这里就不解释了,我会在后面对ActiveMQ的API进行详细的说明。执行代码后,ActiveMQ的管控台界面如下:


Consumer(消费者):

public class Consumer {
    public static void main(String[] args) throws JMSException {
        //1.建立ConnectionFactory工厂对象,需要填入用户名、密码以及ActiveMQ地址,默认端口为tcp://localhost:61616
        ConnectionFactory factory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_USER, ActiveMQConnectionFactory.DEFAULT_PASSWORD,
                "tcp://192.168.1.104:61616");
        //2.通过ConnectionFactory工厂对象创建Connection连接,并调用Connection对象的start方法开启连接,默认为关闭状态
        Connection connection = factory.createConnection();
        connection.start();
        //3.通过Connection对象创建Session会话(上下文环境对象),用于接收和发送消息,参数一:是否开启事务,参数二:签收模式,一般设置为自动签收
        Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
        //4.通过Session对象创建Destination对象,用来指定生产消息和消费消息来源的对象,在PTP中,Destination被称为Queue(队列),
        //在Publish/Subscribe模式,Destination被称为Topic(主题)。程序中可以有多个Queue和Topic。
        Destination destination = session.createQueue("queue1"); //这里的名字需要与生产者的一样
        //5.通过Session对象创建消息的发送和接收对象(生产者和消费者)MessageProducer和MessageConsumer
        MessageConsumer consumer = session.createConsumer(destination);

        while (true) {//循环的监听,一有消息就处理
            //该方法会阻塞,直到接收到消息,还有receive(long l)阻塞指定的时间,receiveNoWait()不阻塞
            TextMessage message = (TextMessage) consumer.receive();
            if(message == null)
                break;
            System.out.println("接收到:" + message.getText());
        }

        if(connection != null) {
            connection.close();
        }
    }
}
执行Consumer,控制台打印:


ActiveMQ管控台:消息已被消费


7.ActiveMQ的安全验证机制

修改conf目录下的activemq.xml文件,在123行后加入如下代码:


配置完成后,重启ActiveMQ,重新运行Producer生产者,控制台会报如下错误:

需要修改在创建ConnectionFactory时传入的用户名和密码:

ConnectionFactory factory = new ActiveMQConnectionFactory("hyy",
                "hyy", "tcp://192.168.1.104:61616");

8.Publish/Subscribe模式

发布者:

public class TopicPublisher {  
    public static void main(String[] args) throws JMSException {  
        ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");  
        Connection connection = factory.createConnection();  
        connection.start();  
          
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);  
        Topic topic = session.createTopic("myTopic.messages");  
  
        MessageProducer producer = session.createProducer(topic);  
        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);  
  
        while(true) {  
            TextMessage message = session.createTextMessage();  
            message.setText("message_" + System.currentTimeMillis());  
            producer.send(message);  
            System.out.println("Sent message: " + message.getText());  
  
            try {  
                Thread.sleep(1000);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
        }  
  
//      session.close();  
//      connection.stop();  
//      connection.close();  
    }  
}  

订阅者:

public class TopicSubscriber {  
    public static void main(String[] args) throws JMSException {  
        ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");  
        Connection connection = factory.createConnection();  
        connection.start();  
          
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);  
        Topic topic = session.createTopic("myTopic.messages");  
  
        MessageConsumer consumer = session.createConsumer(topic);  
        consumer.setMessageListener(new MessageListener() {  
            public void onMessage(Message message) {  
                TextMessage tm = (TextMessage) message;  
                try {  
                    System.out.println("Received message: " + tm.getText());  
                } catch (JMSException e) {  
                    e.printStackTrace();  
                }  
            }  
        });  
//      session.close();  
//      connection.stop();  
//      connection.close();  
    }  
} 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值