ActiveMQ知识点

###什么是中间件?

非操作系统软件,非业务应用软件,不是直接给最终用户使用,不能直接给用户带来价值的软件,我们就可以称为中间件(比如Dubbo,Tomcat,Jetty,Jboss都是属于的)。

中间件被描述为为应用程序提供操作系统所提供的服务之外的服务,简化应用程序的通信、输入输出的开发,使他们专注于自己的业务逻辑。

###什么是消息中间件?

百度百科解释:消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信。

关键点:关注于数据的发送和接受,利用高效可靠的异步消息机制传递机制集成分布式系统。

###为什么要使用消息中间件

举几个例子,我想你就会明白了。(其实使用消息中间件主要就是为了解耦合和异步两个作用)

1:秒杀系统。100件商品,几十万个人在抢,那这个怎么弄呢?总不能就把服务器给宕机了吧。那么就可以把用户的请求进行缓存,然后再异步处理。

2:系统A给系统B进行通信,而系统B需要对A的消息进行相应处理之后才能给A反馈,这时候,总不能让A就傻傻等着吧。那么,这就是异步的功能。

3:假设一个电商交易的场景,用户下单之后调用库存系统减库存,然后需要调用物流系统进行发货,如果交易、库存、物流是属于一个系统的,那么就是接口调用。但是随着系统的发展,各个模块越来越庞大、业务逻辑越来越复杂,必然是要做服务化和业务拆分的。这个时候就需要考虑这些系统之间如何交互,第一反应就是RPC(Remote Procedure Call)。系统继续发展,可能一笔交易后续需要调用几十个接口来执行业务,比如还有风控系统、短信服务等等。这个时候就需要消息中间件登场来解决问题了。

###什么是ActiveMQ呢?

ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。

ActiveMQ是一种消息中间件,有两种模式。一种点对点模式 发布者将发布的消息发送给服务器,等待用户监听并接受数据;第二种订阅模式 发布者将消息发布给消息服务器,让服务器将所有的数据直接转发给再监听的用户,进行一对多通信(类似微信公众号)。

ActiveMQ主要是为了降低程序间的耦合,以及异步执行处理时间较长的代码(如网络通信)。

(1)、点对点模式[P2P]

创建一个生产者类

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

public class MessageProducer {

	//设置ActivMQ的连接地址
    private static final String url = "tcp://127.0.0.1:61616";
    //设置发送消息的队列名称
    private static final String queueName = "queue-text";
    
    public static void main( String[] args ) throws JMSException
    {
        // 1、创建连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
        // 2、创建连接对象
        Connection connection = connectionFactory.createConnection();
        // 3、启动连接
        connection.start();
        // 4、创建会话
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        // 5、创建消息目标
        Queue queue = session.createQueue(queueName);
        // 6、创建生产者
        javax.jms.MessageProducer producer = session.createProducer(queue);
        for (int i=0;i<50;++i) {
            // 7、创建消息
            TextMessage textMessage = session.createTextMessage("JMS消息  " + i);
            // 8、发布消息
            producer.send(textMessage);
            System.out.println("发送的消息为:" + "JMS消息  " + i);
        }
        // 9、关闭连接
        connection.close();
    }
}

 创建一个消费者类

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

public class MessageConsumer {
	//设置ActivMQ的连接地址
    private static final String url = "tcp://127.0.0.1:61616";
    //设置接收消息的队列名称
    private static final String queueName = "queue-text";
    
    public static void main( String[] args ) throws JMSException
    {
        // 1、创建连接工厂
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
        // 2、创建连接对象
        Connection connection = connectionFactory.createConnection();
        // 3、启动连接
        connection.start();
        // 4、创建会话createSession
        //第一个参数表示是否支持事务,第二个参数是客户端接收确认模式,Session.AUTO_ACKNOWLEDGE是自动确认,Session.CLIENT_ACKNOWLEDGE 客户端通过调用消息的 acknowledge 方法签收消息。
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        // 5、创建消息目标
        Queue queue = session.createQueue(queueName);
        // 6 、创建消费者 
        javax.jms.MessageConsumer consumer = session.createConsumer(queue); 
        // 7、设置消费者监听 
        consumer.setMessageListener(new MessageListener() {
			
			@Override
			public void onMessage(Message message) {
				TextMessage textMessage = (TextMessage) message;
				try {
					System.out.println("接收的消息为:" + textMessage.getText());
				} catch (JMSException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
    }
}

操作方式a

运行下生产者的类Producer.java,将消息存到ActiveMQ服务器上;
查看ActiveMQ中的队列信息拥有100条信息,这时候运行一个消费者(Consumer.java)去消费这100条信息;
查看ActiveMQ上的信息,100条信息全被这个1个消费者接收。

操作方式b

同时运行三个消费者(Consumer.java执行三次后可在console切换不同类的控制台查看),再运行一个生产者;
可以看到这100条消息被这三个消费者平分了。

 点对点模式主要用于消除程序高并发高峰对数据库造成的巨大压力,可以通过使用消息队列,让消费者进程从消息队列中获取数据,然后异步将数据写入数据库,由于消息队列的服务处理速度远快于数据库,因此用户的响应延迟可得到有效改善。

(2)、订阅模式(非持久模式)[发布/订阅 Pub/sub]

代码结构与(1)相同,只是session创建的不再是创建队列消费者,而是创建主题消费者。

Queue queue = session.createQueue(queueName);
javax.jms.MessageConsumer consumer = session.createConsumer(queue); 
//替换成
Topic topic = session.createTopic(topicName);//非持久订阅
javax.jms.MessageConsumer consumer = session.createConsumer(topic);

之后先运行消费者,再运行生产者,消费者才能接受到信息,否则生产者发布信息时若没有在监听的消费者则会将信息丢弃,这样消费者是接收不到信息的。

同时运行多个消费者,再运行生产者,消费者将获取生产者发布的所有消息。

(3)、订阅模式(持久订阅)

持久订阅模式的客户端需要创建一个链接id,以保证服务器确认该客户端是否已消费信息,创建完订阅模式,之后不再是创建一个消费者,而是创建一个带有id的用户,这个用户id是唯一的,若有两个相同的id连接,则会报错

//针对Consumer中的Connection设置客户端ID
Connection connection = connectionFactory.createConnection();
connection.setClientID("xiaoxiao1");
...
//创建持久订阅 即未在发布者发布时监听消息,在之后也能接收消息
TopicSubscriber subscriber = session.createDurableSubscriber(topic, "xiaoxiao1");

//针对Producer生产者需要将消息模式设为持久订阅模式
MessageProducer producer = session.createProducer(topic);
producer.setDeliveryMode(DeliveryMode.PERSISTENT);

运行用户消费者(Consumer.java),创建连接id,之后将用户连接关闭,启动生产者(Producer.java)发布消息,最后在重新连接用户获取信息。当用户离线状态时,发布者发布的消息会将信息存在activeMQ服务器上,等待用户监听时将消息发送给用户。生成的用户会在subscribers中显示。

(2)与 (3)的区别

持久传输和非持久传输最大的区别是:采用持久传输时,传输的消息会保存到磁盘中(messages are persisted to disk/database),即“存储转发”方式。先把消息存储到磁盘中,然后再将消息“转发”给订阅者。

采用非持久传输时,发送的消息不会存储到磁盘中。

采用持久传输时,当Borker宕机 恢复后,消息还在。采用非持久传输,Borker宕机重启后,消息丢失。比如,当生产者将消息投递给Broker后,Broker将该消息存储到磁盘中,在Broker将消息发送给Subscriber之前,Broker宕机了,如果采用持久传输,Broker重启后,从磁盘中读出消息再传递给Subscriber;如果采用非持久传输,这条消息就丢失了。

 

############################ActiveMQ集群############################
###为什么要进行集群呢?
原因一:实现高可用:以排除单点故障所引起的服务终端。
原因二:实现负载均衡:以提升效率为更多的客户进行服务。


###集群的方式有哪些?
方式一:客户端集群:多个客户端消费同一个队列。
方式二:Broker clusters:多个Broker之间同步消息。(实现负载均衡)这个的实现原理主要是通过网络连接器来进行。
网络连接器:用于配置ActiveMQ服务器与服务器之间的网络通讯方式,用于服务器透析消息。主要分为静态连接和动态连接。
方式三:Master Slave :实现高可用。
这种方式的话,可以联想到Mysql的主从配置和Zookeeper的负载均衡的主竞争关系master。
我们在实际的开发中,一般都是将方式二和方式三进行集成,从而实现高可用和负载均衡。下面的话,我也就这样的配置思想来进行讲解:(通过三台服务器来模拟消息集群的实现)
————————————————
细节请参考原文链接:https://blog.csdn.net/cs_hnu_scw/article/details/81040834

//通过集群的方式进行消息服务器的管理
//failover进行动态转移,当某个服务器宕机,选择其他服务器
//randomize表示随机选择
private static final String url = "failover:(tcp://127.0.0.1:61616,tcp://127.0.0.1:61617,tcp://127.0.0.1:61618)?randomize=true";

 

activeMQ(网络端口)

activeMQ服务器(jetty服务端口)

生产者Producter

tcp://127.0.0.1:61617

tcp://127.0.0.1:61618

服务器B-8162

服务器C-8163

消费者Consumer

tcp://127.0.0.1:61616

tcp://127.0.0.1:61617

tcp://127.0.0.1:61618

服务器A-8161

服务器B-8162

服务器C-8163

首先,是要确保三个ActiveMQ服务器都进行打开。

分析:当三个都服务都运行之后,我们从浏览器运行各自的地址,会发现:

比如:我这里的三个服务的地址分别如下:

http://127.0.0.1:8161/

http://127.0.0.1:8162/

http://127.0.0.1:8163/

前两个地址可访问,第三个不行。为什么呢?

因为B和C是一种master/slave的方式,当B运行之后就获得了master的权限,那么C服务是可以看到是一种监听的状态,只有当B宕机之后,才有可能获取master的资源权限,所以,这时候C的地址当然就无法访问啦。这就是负载均衡的一种主/从服务的结构。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值