MQ
Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法,消息中间件
RPC: 异步调用,及时获得调用结果,具有强一致性结果,关心业务调用处理结果
消息队列:两次异步RPC调用,将调用内容在队列中进行转储,并选择合适的时机进行投递(错峰流控)
系统间直接调用
- 系统之间接口耦合比较严重
- 微服务架构之前,一个功能会被拆为多个函数(子模块),写程序时一般链式调用,增加模块时代码的改动量太大 - 面对大流量并发容易被冲垮
- 每个接口模块的吞吐能力是有限的,需要流量缓冲池来保证后端系统按照自身吞吐能力进行消费达到削峰 - 等待同步存在性能问题
- 强弱依赖梳理能够将非关键调用链路的操作异步化以提高整体系统的吞吐能力
作用
解耦
异步提升效率
流量削峰
缺点
下载安装
-
ACMQ基于Java,所以需要现在linux上安装好Java环境
-
官网Linux下载ActiveMQ
http://activemq.apache.org/
-
按照步骤
http://blog.csdn.net/gebitan505/article/details/55096222
-
启动
./ activemq start
查看程序启动是否成功
ACMQ默认端口为61616
- 查看进程
ps -ef|grep activemq - 查看端口是否被占用
netstat -apn| grep 61616 - 查看端口是否被占用
lsof -i:61616
启动时指定日志输出文件
activemq日志默认的位置是在:%activemq安装目录%/data/activemq.log
service activemq start > /usr/local/raohao/activemq.log
ActiveMQ控制台
- 访问activemq管理页面地址:http://IP地址:8161/(注意81616是后台端口号,8161是前台端口号)
- 账户admin 密码admin
- 先ping通主机和linux(一定要先关闭防火墙)
适用场景
- 最主要是用以实现实现高性能、高可用、可伸缩和最终一致性架构
- 异步控制消息的消费处理
- 控制消息的消费顺序
- 可以和spring/springboot整合简化代码
- 配置集群容错的mq集群
队列
pom.xml导入依赖
<dependencies>
<!-- activemq 所需要的jar 包-->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.9</version>
</dependency>
<!-- activemq 和 spring 整合的基础包 -->
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>3.16</version>
</dependency>
</dependencies>
队列消息生产者
package com.at.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
public class JmsProduce {
// linux 上部署的activemq 的 IP 地址 + activemq 的端口号
public static final String ACTIVEMQ_URL = "tcp://118.24.20.3:61626";
// 目的地的名称
public static final String QUEUE_NAME = "jdbc01";
public static void main(String[] args) throws Exception{
// 1 按照给定的url创建连接工厂,这个构造器采用默认的用户名密码。该类的其他构造方法可以指定用户名和密码。
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
// 2 通过连接工厂,获得连接 connection 并启动访问。
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
// 3 创建会话session 。第一参数是是否开启事务, 第二参数是消息签收的方式
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
// 4 创建目的地(两种 :队列/主题)。Destination是Queue和Topic的父类
//注意此处导包时要选择Queue(javax.jms)
Queue queue = session.createQueue(QUEUE_NAME);
// 5 创建消息的生产者
MessageProducer messageProducer = session.createProducer(queue);
// 6 通过messageProducer 生产 3 条 消息发送到消息队列中
for (int i = 1; i < 4 ; i++) {
// 7 创建消息
TextMessage textMessage = session.createTextMessage("msg--" + i);
// 8 通过messageProducer发送给mq
messageProducer.send(textMessage);
}
// 9 关闭资源
messageProducer.close();
session.close();
connection.close();
System.out.println(" **** 消息发送到MQ完成 ****");
}
}
在ActiveMQ控制台显示如下:
- Number Of Pending Messages:
等待消费的消息,这个是未出队列的数量,公式=总接收数-总出队列数。
- Number Of Consumers:
消费者数量,消费者端的消费者数量。
- Messages Enqueued:
进队消息数,进队列的总消息量,包括出队列的。这个数只增不减。
- Messages Dequeued:
出队消息数,可以理解为是消费者消费掉的数量。
当有一个消息进入这个队列时,等待消费的消息是1,进入队列的消息是1。
当消息消费后,等待消费的消息是0,进入队列的消息是1,出队列的消息是1。
当再来一条消息时,等待消费的消息是1,进入队列的消息就是2
队列消息消费者
package com.at.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
// 消息的消费者
public class JmsConsumer {
public static final String ACTIVEMQ_URL = "tcp://118.24.20.3:61626";
public static final String QUEUE_NAME = "jdbc01";
public static void main(String[] args) throws Exception{
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
javax.jms.Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(QUEUE_NAME);
// 5 创建消息的消费者
MessageConsumer messageConsumer = session.createConsumer(queue);
while(true){
// reveive() 一直等待接收消息,在能够接收到消息之前将一直阻塞。 是同步阻塞方式 。和socket的accept方法类似的
// reveive(Long time) : 等待n毫秒之后还没有收到消息,就是结束阻塞
// 因为消息发送者是 TextMessage,所以消息接受者也要是TextMessage,一定要保证一致
TextMessage message = (TextMessage)messageConsumer.receive();
if (null != message){
System.out.println("****消费者的消息:"+message.getText());
}else {
break;
}
}
messageConsumer.close();
session.close();
connection.close();
}
}
异步监听式消费者
package com.at.activemq.queue;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
// 消息的消费者 也就是回答消息的系统
public class JmsConsumer {
public static final String ACTIVEMQ_URL = "tcp://118.24.20.3:61626";
public static final String QUEUE_NAME = "jdbc01";
public static void main(String[] args) throws Exception{
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
javax.jms.Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(QUEUE_NAME);
MessageConsumer messageConsumer = session.createConsumer(queue);
/* 通过监听的方式来消费消息,是异步非阻塞的方式消费消息。
通过messageConsumer 的setMessageListener 注册一个监听器,当有消息发送来时,系统自动调用MessageListener 的 onMessage 方法处理消息
*/
//注意MessageListener是一个接口,此处new接口实现一个匿名内部类
messageConsumer.setMessageListener(new MessageListener() {
public void onMessage(Message message) {
// instanceof 判断是否A对象是否是B类的子类,要确保消息种类
if (null != message && message instanceof TextMessage){
TextMessage textMessage = (TextMessage)message;
try {