上一篇文章对ActiveMQ有了初步认识,了解了其大致原理。接下来说说实战中ActiveMQ的应用。
幸运的金荷,公众号:梁同学CodingActiveMQ(一)
八、Broker
*上一篇讲到,启动mq时可以指定,将启动信息保存在指定目录的命令
./activemqstart >/myactiveMQ/run_activemq.log
当然也有类似的启动的时候加载指定配置文件的命令
./activemq start xbean:file/myactive/active-apche-5.15.13/conf/active02.conf
含义:Broker相当于一个MQ的实例,之前都是通过虚拟机来跑,现在给我们提供了通过代码的方式来启动我们的MQ实例。以代码的形式,将ActiveMQ嵌入到Java代码中。
1.依赖pom
<!--Broker-没有这个依赖会报jackson绑定失败-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.15.9</version>
</dependency>
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>3.16</version>
</dependency>
2. 在代码中运行Broker
//ActiveMQ也支持在jvm中通信基于嵌入式的broker
BrokerService brokerService = new BrokerService();
brokerService.setUseJmx(true);
brokerService.addConnector("tcp://localhost:61616");
brokerService.start();
3.在控制台可以看到服务已经启动。修改队列生产者和消费者的uri连接地址
private static final String ACTIVEMQ_URL = "tcp://localhost:61616";
4.运行生产者和消费者
九、SpringBoot整合MQ
1.导入依赖
<!--SpringBoot整合ActiveMQ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
2.新建-队列生产者的配置文件
server:
port: 7777
spring:
activemq:
broker-url: tcp://192.168.91.130:61616 #自己linux服务器上的地址
user: admin
password: admin
jms:
pub-sub-domain: false # false = Queue | true = Topic
#自己定义队列名称
myqueue: boot-active-queue
3.将队列生产者的配置文件做成配置文件来调用
@Component
@EnableJms
public class ConfigBean {
@Value("${myqueue}")
private String myqueue;
@Bean //<bean id="" class="">
public Queue queue(){
return new ActiveMQQueue(myqueue);
}
}
4.建立一个消息的生产者
@Component
public class Queue_Produce {
//利用MQ给我们提供的Template来操作消息
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
//获取上面配置的队列
@Autowired
private Queue queue;
public void produceMsg(){
jmsMessagingTemplate.convertAndSend(queue,"******"+ UUID.randomUUID().toString().substring(0,6));
}
//延迟5秒发送
@Scheduled(fixedDelay = 5000L)
public void produceMsgScheduled(){
jmsMessagingTemplate.convertAndSend(queue,"******Scheduled"+ UUID.randomUUID().toString().substring(0,6));
log.info("send Scheduled Message");
}
}
5.新建-队列消费者的配置文件
server:
port: 8888
spring:
activemq:
broker-url: tcp://192.168.91.130:61616 #自己linux服务器上的地址
user: admin
password: admin
jms:
pub-sub-domain: false # false = Queue | true = Topic
#自己定义队列名称
myqueue: boot-active-queue
6.监听队列生产者发送的消息
@Component
public class Queue_Consumer {
@JmsListener(destination = "${myqueue}")
public void receive(TextMessage textMessage) throws Exception{
System.out.println("消费者接收到消息:"+textMessage.getText());
}
}
7.启动消费者、生产者进行测试
8.可以看到,生产者每隔5秒自动发送一条消息到MQ,消费者启动着监听接收并打印出了消息。
9.主题,也和队列大同小异。只是注意如下
① pub-sub-domain: true # false = Queue | true = Topic
② new的是Topic
@Bean
public Topic topic(){
return new ActiveMQTopic(topicName);
}
③配置的是主题,不是之前的队列
@Autowired
private Topic topic;
④先启动主题的消费者。更改端口号在运行主程序。再修改端口号运行主程序。这样便有了两个消费者,最后在启动生产者。模拟了“发布-订阅”。
十、ActiveMQ的传输协议
之前演示的例子中,默认都采用的是tcp://协议进行的MQ连接。除此之外,还有很多协议也可以用来进行传输。例如nio://协议
1.打开mq的配置文件。
①可以看到我们之前用的是openwrie协议描述,URI头采用的tcp://这是MQ的默认消息协议。
②除了openwrie协议之外,还有其他例如amqp\stomp\mqtt\ws协议。
2. NIO协议
修改conf配置文件
添加<transportConnector name=”nio”uri=”nio//0.0.0.0:61618?trace=true”/>
打开mq控制台Connections可以看到nio的身影
将之前代码中的tcp换成nio
3. auto+nio协议
auto+nio的协议:代表了将上述的amqp\stomp\mqtt\ws协议都集成到了一起外加nio协议。
<transportConnector name=”auto+nio”uri=”auto+nio//0.0.0.0:61618?trace=true”/>
十一、ActiveMQ的消息存储和持久化
1.持久化机制有哪些?
AMQ、KehaDB、LevelDB、JDBC、JDBC Message Store With ActiveMQ Journal(日志)
2.各个机制的特点?
①AMQ:采用文件存储~ 类似于Redis的dump.rdb(时间间隔内写入磁盘)
②KehaDB:
默认消息存储机制
类似于Redis的appendOnly.aof(日志追加)
默认地址为/myactiveMQ/apache-activemq-5.15.13/data/Kahadb
消息存储使用一个日志事务文件db-<num>.log和仅仅使用一个索引文件db.data来存储它所有的地址。
存储原理:4类文件1把锁
db-<num>.log:前身AMQ,默认大小32MB,超过了它,自动db-<num+1>.log
db.data:BTree索引
db.redo:强制退出后,恢复BTree索引
lock:文件锁
db.free:空闲页(字典)
③LevelDB:和KehaDB非常相似,也是基于文件的本地数据库存储形式,使用LevelDB索引。
④JDBC持久化机制-步骤
采用的MQ+Mysql组合
添加mysql数据库驱动jar包到lib文件夹
jdbcPersistenceAdapter配置
<jdbcPersistenceAdapterdataSource="#mysql-ds" createTablesOnStartup="false"/>
注意:createTablesOnStartup默认true,一般在第一次启动后将其改为false
更改activemq.conf数据库连接池配置
mysql-ds引用持久化数据库的bean名称存放位置
<bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:// 192.168.0.110:3306/activemq?relaxAutoCommit=true"/>
<property name="username" value="root"/>
<property name="password" value=""/>
<property name="poolPreparedStatements" value="true"/>
</bean>
建仓SQL和建表 (*activemq启动日志文件 /data/activemq.log)
上述步骤若都操作正确,则会在windows数据库(配置文件中填写的数据库名-实现手动建立好)新建3张表。
注意:我在试验过程中,发现不管怎么更改配置文件,mq就是启动不起来,查看日志文件发现经常报下面的异常。错误解决办法。https://blog.csdn.net/lsxy117/article/details/47207567utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
activemq_acks
activemq_lock
activemq_msgs
代码运行验证、数据库情况
开启了持久模式(默认开启)DeliveryMode.Persisten | 非持久模式DeliveryMode.NON_Persisten | |
点对点类型中: activemq_msgs | 消息保存在broker或者数据库msg中 | 消息保存在内存中 |
一对多类型中: activemq_acks | connection.setClientID("z4"); TopicSubscriber topicSubscriber = session.createDurableSubscriber(topic, "备注");//创造持久化订阅者 connection.start(); 会永久存在在acks表中,除非控制台将订阅者删除掉 |
小总结、开发有坑
1.数据库jar包:mysql-jdbc驱动包放在/lib包下
2.在jdbcPersistenceAdapter标签中,createTablesOnstartup第一次为true后,下次启动将其改为false
3.下划线有坑:BeanFactory not initialized or alreadyclosed.
机器操作系统机器名中有”_”符号。改名重启即可。
⑤ JDBC Message Store With ActiveMQJournal(日志)
使用高速缓存写入技术。
生产者—快速生产了大量消息—到journal文件。
消费者—消费速度也很快。
journal文件挡在mysql之前。
消息被消费者消费只剩20%再存到Mysql。大大减少了消息和Mysql的压力。
此时,再启动队列生产者,数据表msgs中不会再插入。消费者也照常运行。
Ps:消息都抵挡在了journal里了,还没到mysql。
3.ActiveMQ持久化机制小总结
JMS的可靠性?
持久性、事务、签收、可持久化:MQ所在服务器down了消息不会丢失的机制
演化过程?
AMQ(最初)---High performance journal(同步推出Mysql解决方案)---KehaDB(默认)---LevelDB(基于文件)---Zookeeper+LevelDB(集群化方案)
未完待续。。。