目录
8.zookeeper+replicated-leveldb-store主从集群
ActiveMQ安装教程
下载并启动
下载好压缩包,开始解压
如图解压完毕
如果想要把mq的消息持久化到数据库,需要将数据库的jar包放到lib里。
重命名为activemq,执行mv
进入bin里,./activemq start ,启动,activemq默认进程的端口是61616,所以防火墙需要开放这个端口。
这个61616是后台进程端口号,前台是8161访问。
重启restart ,关闭 stop
查看进程里的pid与61616端口占用的进程编号是否一致,一致说明启动的就是activemq。
以前用 ps -ef|grep activemq,现在用ps -ef|grep activemq|grep -v grep,然后查看端口:netstat -anp|grep 61616u或者lsof -i:61616即可。
这是四种查看进程的方法。
另外如果没有任何输出说明61616没有启动
如图都是同一个进程编号,这样也是用来排查是否有别的应用占用了61616端口。
复制activemq.xml一份放在同一个文件夹 cp activemq.xml activemq02.xml,取名为activemq02.xml,然后针对02这个配置启动,类似于redis不同的集群配置不同。
带日志的启动方式
进入bin目录,先mkdir -p myrunmq.log,然后./activemq start > /myrunmq.log
如图没有任何提示,提示都写到了log文件里。
Activemq控制台
采用61616端口提供JMS服务,采用8161端口提供管理控制台服务
启动后台服务进程61616端口,前台是用8161访问,所以用windows访问时得开通8161端口,发现无法访问,
因为没有修改ip地址,进入conf/jetty.xml里,将此处的127.0.0.1改为如图Linux的IP地址即可
重启mq然后访问成功,输入admin/admin,用户名与密码一致
配置NIO+TCP
Activemq默认使用tcp,他的出场默认是BIO+TCP,接下来配置NIO+TCP
先复制一份activemq.xml,然后如图添加一行
<transportConnector name="nio" uri="nio://0.0.0.0:61618?trace=true"/>
然后启动mq,访问并进入connections,发现nio添加成功
如果要用nio,代码里注意改正,tcp->nio,61616改成配置的61618即可
NIO增强
即NIO不仅支持TCP,还支持多种协议,例如
如图替换掉原先nio配置的那一行
<transportConnector
name="auto+nio" uri="auto+nio://0.0.0.0:61608?maximumConnections=1000&wireFormat.maxFrameSize=104857600&org.apache.activemq.transport.nio.SelectorManager.corePoolSize=20&org.apache.activemq.transport.nio.SelectorManager.maximumPoolSize=50"/>
如图配置成功
接着修改端口为61608,即nio://…:61608访问即可。
TCP与NIO必须掌握,其余协议可忽略。
activemq持久化机制
redis有RDB与AOF持久化机制,为了保证activemq本机宕机后还有一份备份
Activemq消息持久化之jdbc配置mysql
1.添加mysql jar包
首先将mysql jar包复制到lib里,bin.jar结尾的是windows的。
2.jdbcPersistenceAdapter配置
接着改activemq,如图默认是kahadb,将其注释掉,配置好jdbc的mysql配置。
<persistenceAdapter>
<jdbcPersistenceAdapter dataSource="#my-ds"/>
</persistenceAdapter>
3.数据库连接池配置
AMQ 5.x
<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://localhost/activemq?relaxAutoCommit=true"/>
<property name="username" value="activemq"/>
<property name="password" value="activemq"/>
<property name="poolPreparedStatements" value="true"/>
</bean>
官网上给的是localhost地址,实际工作中数据库肯定在另一台服务器。
例如本地my在linux上,mysql在windows上就不能这样配置,另外连接的数据库名为activemq(不一定非要叫activmq,随便)需要创建。另外此处使用的连接池为dbcp2,可以根据实际情况选用。使用不同的数据库连接池注意需要额外导入支持的jar包,此处只用了mysql一个jar,因此可以完全支持dbcp2。
如图,该配置放在broker标签与import标签之间。
4.sql建仓与建表说明
1)先创建一个数据库:create database activemq;
2)连接成功后会自动创建三张表,如图activemq_msgs,activemq_acks,activemq_lock。
如有特殊情况,手动建表。
3)启动activemq,由于配置了mysql连接本地wndows,启动较慢,等一会再访问。
然后访问浏览器以及mysql,看看是否访问成功,是否有三个表正常建立。
如图能正常访问,表建立正常(记住关闭mysql,重新打开才能看到)
至此,配置成功完成了。
5.代码运行验证
发送方发送消息都记录在msgs表,不同在于点对点消息消费后就删了,主题订阅会一直存在。
主题订阅对应acks表。
1.点对点
创建一个生产者
package com.atguigu.demo;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.transport.stomp.Stomp;
import javax.jms.*;
/**
* @author yss
* @time 2020/8/29 - 16:50
*/
public class JmsProduce {
public static final String ACTIVEMQ_URL="tcp://192.168.1.200:61616";
public static final String QUEUE_NAME="jdbc01";
public static void main(String[] args) throws JMSException {
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(QUEUE_NAME);
MessageProducer messageProducer = session.createProducer(queue);
messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT); //持久化
for(int i=1;i<=3;i++){
TextMessage textMessage = session.createTextMessage("textMessage msg---"+i);
messageProducer.send(textMessage);
}
messageProducer.close();
session.close();
connection.close();
System.out.println("******消息发布到MQ完成");
}
}
先启动队列生产者,运行成功,已有三条队列。
然后mysql的msgs表里已有三条持久化的记录信息。表说明略,上方有说明。
接着启动消费者
package com.atguigu.demo;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* @author yss
* @time 2020/8/29 - 16:50
*/
public class JmsConsumer {
public static final String ACTIVEMQ_URL="tcp://192.168.1.200:61616";
public static final String QUEUE_NAME="jdbc01";
public static void main(String[] args) throws JMSException {
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
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);
while (true)
{
TextMessage textMessage = (TextMessage)messageConsumer.receive(4000L);
if(null!=textMessage){
System.out.println("******消费者接收到消息:"+textMessage.getText());
}else{
break;
}
}
messageConsumer.close();
session.close();
connection.close();
System.out.println("******消息发布到MQ完成");
}
}
消费者此处设置4秒后消费离开,所以如图消费完4秒后离开了。
然后看数据库里的消息,消费完都清空了。
此处改成DeliveryMode.NON_PERSISTENT
则不会保存到数据库。
2.主题
消费者编码
package com.atguigu.demotopic;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* @author yss
* @time 2020/8/29 - 17:28
*/
public class TopicConsumer_Persistent {
public static final String ACTIVEMQ_URL="tcp://192.168.1.200:61616";
public static final String TOPIC_NAME="topic-jdbc-PERSISTENT";
public static void main(String[] args) throws JMSException {
//1.创建连接工厂,使用默认用户名密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.获得连接并启动
Connection connection = activeMQConnectionFactory.createConnection();
//3.需要在连接上设置消费者id,用来标识消费者
connection.setClientID("atguigu01");
//4.创建会话,此步骤有两个参数,第一个是否以事务的方式提交,第二个默认的签收方式
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
//5.创建主题
Topic topic = session.createTopic(TOPIC_NAME);
//要创建TopicSubscriber来订阅
TopicSubscriber topicSubscriber = session.createDurableSubscriber(topic,"mq-jdbc");
//一定要先运行一次,等于向消息服务中间件注册这个消费者,然后再运行客户端发送信息,这个时候,无论消费者是否在线都会接收到,
//不在线的话,下次连接的时候就会接受到
connection.start();
//接受消息
Message message = topicSubscriber.receive();
while (null!=message)
{
TextMessage textMessage = (TextMessage)topicSubscriber.receive(4000L);
if(null!=textMessage){
System.out.println("******消费者接收到消息:"+textMessage.getText());
}else{
break;
}
}
topicSubscriber.close();
session.close();
connection.close();
System.out.println("******消息发布到MQ完成");
}
}
如图执行订阅成功
接着看acks表
启动生产者
package com.atguigu.demotopic;
import org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.*;
/**
* @author yss
* @time 2020/8/29 - 17:28
*/
public class TopicProduce_Persistent {
public static final String ACTIVEMQ_URL="tcp://192.168.1.200:61616";
public static final String TOPIC_NAME="topic-jdbc-PERSISTENT";
public static void main(String[] args) throws JMSException {
//1.创建连接工厂,使用默认用户名密码
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(ACTIVEMQ_URL);
//2.获得连接并启动
Connection connection = activeMQConnectionFactory.createConnection();
//3.创建会话,此步骤有两个参数,第一个是否以事务的方式提交,第二个默认的签收方式
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
//创建主题
Topic topic = session.createTopic(TOPIC_NAME);
//创建生产者
MessageProducer messageProducer = session.createProducer(topic);
//5.1 要用持久化订阅
messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT); //持久化
//5.2 一定要设置完成持久化后再start这个connection
connection.start();
for(int i=1;i<=6;i++){ //生产6条消息给MQ
TextMessage textMessage = session.createTextMessage("message--persistence-topic:"+i);
messageProducer.send(textMessage);
}
messageProducer.close();
session.close();
connection.close();
System.out.println("******消息发布到MQ完成");
}
}
生成了6个消息,然后数据表msgs也产生了6条数据。
6.小总结以及注意的坑
7.jdbc with journal
即高速缓存配置,官网推荐使用这种配置,说明如下
这种journal日志相当于帮mysql挡了一层。这种类似于jdbc增强。例如点对点以前是直接写进mysql表里,现在是先写进journal,消费者走的是高速缓存,这样可以极大的减轻数据库的压力 ,默认实在7-8分钟后才会写入DB。
配置如下
<persistenceFactory>
<journalPersistenceAdapterFactory
journalLogFiles="4"
journalLogFileSize="32768"
useJournal="true"
useQuickJournal="true"
dataSource="#mysql-ds"
dataDirectory="activemq-data"/>
</persistenceFacory>
8.zookeeper+replicated-leveldb-store主从集群
1.原理
5.9版本后官网推荐使用,这也是企业常用的。
2.zookeeper集群部署规划说明
框住的是一致的,主机linuxIP为192.168.1.200,zookeeper端口分别为:2181,2182,2183,其余一致。
Leader+follower模式的伪分布式集群。
首先下载tar包并解压,tar -zxvf …
进入conf,找到zoo_sample.cfg并重命名为zoo.cfg,因为默认访问的名字叫做zoo.cfg.
cp zoo_sample.cfg zoo.cfg
分别复制三分zookeeper安装好的文件
cp -r zookeeper zk011/2/3
在zookeeper2181里创建一个data文件夹,然后data路径配置到conf里并添加server服务信息如下:
这些端口都放开,防火墙配置下。
server.1=127.0.0.1:2287:3387
server.2=127.0.0.1:2288:3388
server.3=127.0.0.1:2289:3389
然后在2181的data文件夹下创建myid文件,并追加内容为1,echo “1”
然后在2182,2183进行同样的配置,然后分别王myid追加2,3,如下图
然后分别到各自的bin里启动zookeeper服务端,./zkServer.sh start ,jsp查看进程启动成功。
./zkServer.sh status是查看启动状态的。
启动客户端连接,./zkCli.sh -server 127.0.0.1:2181/2/3,如图连接成功。或者如图启动,另注意防火墙端口放行。
如果启动报:Unable to read additional data from server sessionid 0x0
先杀死所有zookeeper进程,然后由于我在zoo.cfg中配置了3台机器,但是只启动了1台,zookeeper就会认为服务处于不可用状态。
zookeeper有个选举算法,当整个集群超过半数机器宕机,zookeeper会认为集群处于不可用状态。
所有,3台机器只启动一台无法连接,如果启动2台及以上就可以连接。
关于zk启动可以写个脚本,先创建要给文件夹myCommand,然后touch zk_batch.sh,内容为
cd /usr/local/zookeeper2181/bin
./zkServer.sh start
cd /usr/local/zookeeper2182/bin
./zkServer.sh start
cd /usr/local/zookeeper2183/bin
./zkServer.sh start
集体关闭将start改stop即可,如果提示权限不够,则chmod u+x zk_batch_stop.sh即可。
3.创建mq的实例
创建三个mq集群目录
创建一个mq_cluster文件夹,进入mq_cluster文件夹,将activemq全部复制这里,分别创建3个。
cp -r /usr/local/activemq mq_node01
4.修改管理控制台端口
分别改端口,进入conf找到jetty.xml分别将端口改为8161,8162,8163。
5.hostname地址映射
vm /etc/hosts 添加LinuxIP地址以及名字,名字随便取。
6.activemq集群配置
分别修改三个节点activemq.xml的brokername,要求brokername都是同一个。
7.三个节点的持久化配置
由于复制的三个节点都是原生态的mq,所有默认的持久化配置是kahaDB,所以现在要换成levelDB,这个配置从官网复制即可。
分别进入activemq.xml,将kahadb注释,
此处的2181,2181,2183端口为上方zookeeper集群的端口,zzyymq-server为上方hostname配置的地址映射。
<persistenceAdapter>
<replicatedLevelDB
directory="${activemq.data}/leveldb"
replicas="3"
bind="tcp://0.0.0.0:63631"
zkAddress="localhost:2181,localhost:2182,localhost:2183"
hostname="zzyymq-server"
zkPath="/activemq/leveldb-stores"
sync="local_disk" />
</persistenceAdapter>
然后如法炮制,分别对02,03节点配置,
bind="tcp://0.0.0.0:63632" bind="tcp://0.0.0.0:63633"
8.修改各节点消息端口
分别修改activemq.xml里openwire对应的端口,
9.按顺序启动3个mq节点
前提zk集群已经成功启动,如图zk集群服务的三个进程成功开启。
或者ps -ef|grep zookeeper|grep -v grep|wc -l
登陆zk服务器里的一个,看看上面mq有没有注册成功,如图三个mq节点成功挂上了。
./zkCli.sh -server 127.0.0.1:2181
查看master,至此mq集群搭建成功。
10.集群可用性测试
查看mq线程:ps -ef|grep activemq|grep -v grep
与理论一致,mq只有一台master提供服务,登陆客户端,使用8161访问:192.168.1.200:8161,8162/3不能访问。
下图对应activem.xm的brokername
代码都能正常访问,然后kill掉该61616端口的进程,8161无法访问,然后8162与8163有一个会成为master继续提供服务,演示略。
待续3