消息中间件

1.ActiveMQ

  • 安装
    在这里插入图片描述
    服务器运行后,我们可以直接访问到activeMQ的界面:
    在这里插入图片描述
    队列模式测试:
    生产者
    1.创建工厂连接对象,需要制定ip和端口号
    ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“tcp://192.168.156.44:61616”);
    2、使用连接工厂创建一个连接对象
    Connection connection = connectionFactory.createConnection();
    3.开启连接
    connection.start();
    4、使用连接对象创建会话(session)对象
    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    5、使用会话对象创建目标对象,包含queue和topic(一对一和一对多)
    Queue queue = session.createQueue(“test-queue”);
    6、使用会话对象创建生产者对象
    MessageProducer producer = session.createProducer(queue);
    7、使用会话对象创建一个消息对象
    TextMessage textMessage = session.createTextMessage(“hello!test-queue”);
    8、发送消息
    producer.send(textMessage);
    9、关闭资源
    producer.close();
    session.close();
    connection.close();

消费者:
1、创建工厂连接对象,需要制定ip和端口号
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“tcp://192.168.156.44:61616”);
2、使用连接工厂创建一个连接对象
Connection connection = connectionFactory.createConnection();
3、开启连接
connection.start();
4、使用连接对象创建会话(session)对象
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
5、使用会话对象创建目标对象,包含queue和topic(一对一和一对多)
Queue queue = session.createQueue(“test-queue”);
6、使用会话对象创建生产者对象
MessageConsumer consumer = session.createConsumer(queue);
7、向consumer对象中设置一个messageListener对象,用来接收消息
在这里插入图片描述

主题模式测试:
生产者
1.创建工厂连接对象,需要制定ip和端口号
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“tcp://192.168.156.44:61616”);
2、使用连接工厂创建一个连接对象
Connection connection = connectionFactory.createConnection();
3.开启连接
connection.start();
4、使用连接对象创建会话(session)对象
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
5、使用会话对象创建目标对象,包含queue和topic(一对一和一对多)
Topic topic = session.createTopic(“test-topic”);
6、使用会话对象创建生产者对象
MessageProducer producer = session.createProducer(topic );
7、使用会话对象创建一个消息对象
TextMessage textMessage = session.createTextMessage(“hello!test-topic”);
8、发送消息
producer.send(textMessage);
9、关闭资源
producer.close();
session.close();
connection.close();

消费者:
1、创建工厂连接对象,需要制定ip和端口号
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“tcp://192.168.156.44:61616”);
2、使用连接工厂创建一个连接对象
Connection connection = connectionFactory.createConnection();
3、开启连接
connection.start();
4、使用连接对象创建会话(session)对象
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
5、使用会话对象创建目标对象,包含queue和topic(一对一和一对多)
Topic topic = session.createTopic(“test-topic”);
6、使用会话对象创建生产者对象
MessageConsumer consumer = session.createConsumer(topic);
7、向consumer对象中设置一个messageListener对象,用来接收消息
在这里插入图片描述
8、程序等待接收用户消息
System.in.read();
9、关闭资源
consumer.close();
session.close();
connection.close();

注意:主题模式下,先打开生产者,再打开消费者,消息不会被消费,因为
topic消息不会再服务器持久化

ActiveMQ整合spring及项目中运用
在这里插入图片描述
在这里插入图片描述

商品添加到数据库的时候,对应也要添加数据到我们的solr索引中

在这里插入图片描述
消费者应该写在我们的搜索工程中,首先添加spring和activeMQ的jar包,然后配置xml文件,再编写一个监听器,当接收到消息时,就讲数据存入索引库

在这里插入图片描述

queue 与 topic 区别

1、点对点(point-to-point,简称PTP)Queue消息传递模型:
一个生产者的消息只能给一个消费者消费
消息缓存在消息队列中,直到消息被消费或过期,才从队列中移除
生产者创建消息到消息中间件,再“均分给消费者”
能够保证数据安全;
2、发布/订阅(publish/subscribe,简称pub/sub)Topic消息传递模型:
每个消息可以有多个消费者。
在主题模式下,消费者获取不到订阅之前的中间件中的消息
数据容易丢失;

消息通信的基本方式有两种:
1、同步方式
两个通信应用服务之间必须要进行同步,两个服务之间必须都是正常运行的。发送程序和接收程序都必须一直处于运行状态,并且随时做好相互通信的准备。
发送程序首先向接收程序发起一个请求,称之为发送消息,发送程序紧接着就会堵塞当前自身的进程,不与其他应用进行任何的通信以及交互,等待接收程序的响应,待发送消息得到接收程序的返回消息之后会继续向下运行,进行下一步的业务处理。
2、异步方式
两个通信应用之间可以不用同时在线等待,任何一方只需各自处理自己的业务,比如发送方发送消息以后不用登录接收方的响应,可以接着处理其他的任务。也就是说发送方和接收方都是相互独立存在的,发送方只管方,接收方只能接收,无须去等待对方的响应。
Java中JMS就是典型的异步消息处理机制,JMS消息有两种类型:点对点、发布/订阅。

ActiveMQ服务器宕机怎么办?
这得从ActiveMQ的储存机制说起。在通常的情况下,非持久化消息是存储在内存中的,持久化消息是存储在文件
中的,它们的最大限制在配置文件的节点中配置。但是,在非持久化消息堆积到一定程度,内存
告急的时候,ActiveMQ会将内存中的非持久化消息写入临时文件中,以腾出内存。虽然都保存到了文件里,但
它和持久化消息的区别是,重启后持久化消息会从文件中恢复,非持久化的临时文件会直接删除。

那如果文件增大到达了配置中的最大限制的时候会发生什么?我做了以下实验:

设置2G左右的持久化文件限制,大量生产持久化消息直到文件达到最大限制,此时生产者阻塞,但消费者可正
常连接并消费消息,等消息消费掉一部分,文件删除又腾出空间之后,生产者又可继续发送消息,服务自动恢复
正常。

设置2G左右的临时文件限制,大量生产非持久化消息并写入临时文件,在达到最大限制时,生产者阻塞,消费者
可正常连接但不能消费消息,或者原本慢速消费的消费者,消费突然停止。整个系统可连接,但是无法提供服
务,就这样挂了。

具体原因不详,解决方案:尽量不要用非持久化消息,非要用的话,将临时文件限制尽可能的调大。

为什么丢消息?

通过抓包得知,ActiveMQ会每隔10秒发送一个心跳包,这个心跳包是服务器发送给客户端的,用来判断客户端死没
死。如果你看过上面第一条,就会知道非持久化消息堆积到一定程度会写到文件里,这个写的过程会阻塞所有动作
,而且会持续20到30秒,由于服务器心跳包的设置,导致发生了java.net.SocketException异常,把缓存里的数
据作废了,没处理的消息全部丢失。

丢消息怎么办?
ActiveMQ持久化【高可用】
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
设置了activeMQ持久化后,即使当activeMQ宕机后重启,未被消费的消息依然能够存在于消息队列中,消费者仍能进行消费。

如何防止消息丢失?
activemq的消息确认机制ACK,对于broker而言,只有接收到ACK指令,才会认为消息被正确的接收或者处理成功了,通过ACK,可以在consumer与Broker之间建立一种简单的“担保”机制.

持久化消息非常慢?
默认的情况下,非持久化的消息是异步发送的,持久化的消息是同步发送的,遇到慢一点的硬盘,发送消息的速度
是无法忍受的。但是在开启事务的情况下,消息都是异步发送的,效率会有2个数量级的提升。所以在发送持久
化消息时,请务必开启事务模式。其实发送非持久化消息时也建议开启事务,因为根本不会影响性能。

消息的不均匀消费
有时在发送一些消息之后,开启2个消费者去处理消息。会发现一个消费者处理了所有的消息,另一个消费者根
本没收到消息。原因在于ActiveMQ的prefetch机制。当消费者去获取消息时,不会一条一条去获取,而是一次
性获取一批,默认是1000条。这些预获取的消息,在还没确认消费之前,在管理控制台还是可以看见这些消息
的,但是不会再分配给其他消费者,此时这些消息的状态应该算作“已分配未消费”,如果消息最后被消费,
则会在服务器端被删除,如果消费者崩溃,则这些消息会被重新分配给新的消费者。但是如果消费者既不消费
确认,又不崩溃,那这些消息就永远躺在消费者的缓存区里无法处理。更通常的情况是,消费这些消息非常耗
时,你开了10个消费者去处理,结果发现只有一台机器吭哧吭哧处理,另外9台啥事不干。 解决方案:
将prefetch设为1,每次处理1条消息,处理完再去取,这样也慢不了多少。(肯定比每次拉去多条要慢)

消费者如果保证消息幂等性,不被重复消费?
网络延迟传输中,会造成进行MQ重试中,在重试过程中,可能会造成重复消费。
使用全局MessageID判断消费方使用同一个,解决幂等性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值