一个机器上启动多个Broker
可以理解成一个伪分布式的ActiveMQ集群。
Linux上:
cd activemq-5.9.0
cp -r conf conf2
针对我安装在windows上的MQ来操作一下。
0.复制文件夹
1.conf2修改里面的一些配置
修改conf2中activemq.xml核心配置文件中broker里面的:broker的名字、存储的位置的名字、客户端连接MQ各种协议端口号:
(1)<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost2" dataDirectory="${activemq.data}">
(2)<persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb2"/>
</persistenceAdapter>
<transportConnectors>
<transportConnector name="openwire" uri="tcp://0.0.0.0:61776?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5772?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61713?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1783?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61714?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
修改访问web界面端口号(conf/jetty.xml):
<bean id="jettyPort" class="org.apache.activemq.web.WebConsolePort" init-method="start">
<!-- the default port number for the web console -->
<property name="port" value="8181"/>
</bean>
2.修改bin2/activemq的文件
前面介绍过的启动MQ的broker(服务),启动的文件是:
cd activemq-5.9.0/bin/
cp activemq activemq2
修改这个文件的内容:
(1)
# Location of the pidfile
if [ -z "$ACTIVEMQ_PIDFILE" ]; then
ACTIVEMQ_PIDFILE="$ACTIVEMQ_DATA/activemq2-`hostname`.pid"
fi(2)
if [ -z "$ACTIVEMQ_CONF" ] ; then
# For backwards compat with old variables we let ACTIVEMQ_CONFIG_DIR set ACTIVEMQ_CONF
if [ -z "$ACTIVEMQ_CONFIG_DIR" ] ; then
ACTIVEMQ_CONF="$ACTIVEMQ_BASE/conf2"
else
ACTIVEMQ_CONF="$ACTIVEMQ_CONFIG_DIR"
fi
fi
3.修改:\bin2\win64\activemq.bat
4.修改:\bin2\win64\wrapper.conf
如果启动不起来,就需要对activemq2文件授权:chmod 751 activemq2,这样就实现了一台机器上启动多个broker。
启动Windows上的两个Broker。就是启动两个bin下的64位下的activemq.bat文件。
访问两个broker的web管理界面:
http://localhost:8161/admin/
http://localhost:8181/admin/
在Myeclipse中使用的时候可以分别连接两个broker,测试发送接收一个消息:
ActiveMQ的网络的连接
ActiveMQ的broker之间的网络连接:
比如现在有两个broker:A、B。broker-A端有自己的生产者和消费者,broker-B端也有自己的生产者和消费者。两个broker之间的通信可以是单向的,也可以是双向的。默认使用的是单向的。
(1)单向通信:比如从A到B。给broker-A发送消息,消息会流到broker-B,在broker-B端可以被消费,但是给broker-B发消息,消息不会流到broker-A,broker-A端的消费者不能消费消息。
(2)双向通信:无论给哪一段发消息,两个broker都能消费消息。
broker之间的网络连接有两种方式:一种是静态发现(静态连接方式),一种是动态发现(动态连接方式)。
(1)静态连接方式
现在来操作一下。修改一个broker中的activemq.xml文件,添加静态网络配置(关于消息的存储还原回原来的KahaDB方式):
默认单向就是从61676-->61776的broker。
针对windows上的操作一下,操作的是tcp端口为61616的那个broker:
<networkConnectors>
<networkConnector name="local network" uri="static://(tcp://localhost:61616,tcp://localhost:61776)" ></networkConnector>
</networkConnectors>//默认的单向就是从61616到61776
重新启动两个broker,测试PTP传递域的代码,运行发送端和接收端。因为默认使用的是单向的连接,现在要测试静态单向连接的broker伪分布式,所以需要修改连接端和消费端连接的端口,分别连接不同的broker:
根据在核心配置文件中配置的静态连接单向方向是61676-->61776,所以就是发给61676的broker,然后消息会传递到61776的broker中。所以可以从61776的broker中进行消费。
运行发送端接收端的代码,查看MQ的web管理界面。因为此时是两个broker,所以需要分别连接两个不同的URL分别查看消息的变化。如果把接收端的端口改为61676,就是生产端和消费端是同一个broker,查看web界面消息的变化都是来自同一个broker,另一个61776的broker是没有变化的。消息就只会在一个broker中进行进出。
针对windows上的MQ:
applicationContext.xml中配置的连接不动:
就是消息是发送给61616的,但是消息会传送到61776上,启动两个broker,启动两个web管理界面:
配置了静态的单向连接,发给61616的消息会传送到61776,所以从61776可以接收到消息。
如果发到61616上,也可以从61616上接收到:
因为两个broker配置了连接,所以两个web界面上都可以看到上面的消息。
所以配置了静态单向连接A->B,发给A消息,从B端也可以接收到消息,当然也可以从A端的消费者中消费消息。但是注意的是:PTP消息是存放在队列中的,消费一次后就清除了,一个消息只能被一个消费者消费。但是Pub/Sub消息,消息是不会清除的,因为他要发布给很多的订阅者,一个消息可以有很多的消费者。
如果applicationContext.xml中配置的连接仍然是61616(没有任何影响)。发送给61776,然后从61616接收就接收不到消息。这是因为:在这个broker集群中配置的是61616-->61776的单向连接,消息不会从61776流向61616的。所以如果消息发送给61776,消费者从61776可以接收到消息,但是从61616接收不到消息,因为消息不能逆向回流。
核心配置文件中网络连接networkConnection的可以使用的属性:
第七个属性是有关负载均衡的时候。比如BrokerB有两个消费者,还有一个远程的BrokerA消费者,属性值是true的时候,BrokerB就会把他的两个消费者当作1个,也就是说BrokerB分消息的时候只会分成两份。如果参数值是false,那么就会把BrokerB的消息分成三份分发。
第八、九个参数的作用是实现消息过滤。我们上面配置的网络连接,发送端BrokerA发送消息的时候会全部的转到接收端BrokerB上,但是有的时候这样是不对的,有的时候是想过滤的,就是说把部分消息转为接收端BrokerB中的。所以如果我们配置的是静态网络连接,想达到消息在Broker之间的过滤就用第九个参数,如果我们配置的是动态网络连接,想达到消息在Broker之间的过滤就用第八个参数。
第十一个参数是设置不同broker的双向网络连接的。比如在核心配置文件中进行下面的使用:
这样配置之后就建立了BrokerA与BrokerB之间的双向连接。A发消息B可以接到,B发消息A可以接到。测试双向连接,需要来回的更改发送端接收端的端口,这样通过web就可以看到结果。
第十二个参数就是我们常说的ActiveMQ的缓存的时候可以缓存的未消费的消息的数量,是为了提高性能的,在这里设置可以缓存的未消费的消息的个数。
比如现在BrokerA和BrokerB配置的静态双向连接,如果说此时BrokerA和BrokerB两端都各自还有消费者,那么到底谁消费的消息会多一点呢?这就涉及到消息消费者的负载均衡,后面讲。
broker双向连接的消息回流
出现上述的消息丢失的情况,即使使用双向网络连接也是解决不了的,所以可以使用ActiveMQ5.6增加的replayWhenNoConsumers属性设置。所以修改两个broker的核心配置文件activemq.xml:
重新启动两个broker,然后测试运行发送端和接收端的代码,演示运行的过程中某个broker下线了,另一个broker端的消费者可以全部消费未消费的消息,包括回流的消息。所以消息可以回流在ActiveMQ的集群中是非常有用的。
针对windows上的ActiveMQ来操作一下上面介绍的消息回流。还是操作61616的activemq.xml文件,在broker标签里面的:
<destinationPolicy>
<policyMap>
<policyEntries>标签里面添加一个policyEntry配置消息回流:
<policyEntry queue=">" enableAudit="false">
<networkBridgeFilterFactory>
<conditionalNetworkBridgeFilterFactory replayWhenNoConsumers="true"/>
</networkBridgeFilterFactory>
</policyEntry>修改networkConnectors标签里面的networkConnector标签,添加duplex="true"双向连接(61616和61776的双向连接):
<networkConnectors>
<networkConnector name="local network" duplex="true" uri="static://(tcp://localhost:61616,tcp://localhost:61776)" ></networkConnector>
</networkConnectors>applicationContext.xml中配置的连接的还是61616,为了测试修改一个PTP类型的发送端和接收端的代码。
上面的修改对conf和conf2中的核心配置文件都做同样的修改。
发送端:
package test1;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
//PTP模式的发送端
public class QueueSender {
public static void main(String[] args) throws Exception {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");//发送到61616上
Connection con = connectionFactory.createConnection();
con.start();
Session session = con.createSession(true, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("my-queue");
MessageProducer producer = session.createProducer(destination);
for(int i=0;i<10;i++){
TextMessage message = session.createTextMessage("message--"+i);
message.setStringProperty("stringProperty"+i, "property1"+i);
producer.send(message);
}
session.commit();
session.close();
con.close();
}
}
接收端:
package test1;
import java.util.Enumeration;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
//PTP模式的接收端
public class QueueReceiver {
public static void main(String[] args) throws Exception {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61776");//从61776接收
Connection con = connectionFactory.createConnection();
con.start();
Enumeration jmsxPropertyNames = con.getMetaData().getJMSXPropertyNames();
while(jmsxPropertyNames.hasMoreElements()){
String element = (String)jmsxPropertyNames.nextElement();
System.out.println("jms name="+element);
}
Session session = con.createSession(true, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("my-queue");
MessageConsumer consumer = session.createConsumer(destination);
int i =0;
while(i<10){
Thread.sleep(2000);//让接收端接收的慢一点
TextMessage message = (TextMessage)consumer.receive();
session.commit();
System.out.println("接收到的消息:"+message.getText()+"--接收到的属性:"+message.getStringProperty("stringProperty"+i));
i++;
}
session.close();
con.close();
}
}
启动bin和bin2下的64位的activemq.bat文件。启动发送端,查看web界面:
然后启动接收端,让他接收两个消息之后下线,观察web界面:
此时61776一端下线了,因为在双向连接中配置了消息回流机制,所以61776端没有消费的消息又回流会61616端了,所以让61616端接收也可以接收到了:
观察web界面:
把61616端的broker称为A,把61776端的broker称为B。理解一下上面的显示:
(1)首先消息发送给A10个,然后B端消费了2个,所以B端还剩8个消息。
(2)配置了消息回流,从A端消费消息,这样B端的消息就回流回了A端,此时A端进来了8个,消费了2个,所以A端还剩6个没有消费。
同理此时B端连接上进行消费的话,消息又会回流进行消费的。
容错的链接Failover协议----broker的负载均衡
上面介绍的是连接MQ的时候使用的协议是failover协议,并且randomize的值必须是true:
解释一下为什么使用failover协议,为什么randomize的值必须是true?
(1)使用failover协议,可以配置连接多个broker的url。这里连接的时候连的还是1个broker。使用broker的时候首先会连接第一个url(broker),但是第一个broker挂了怎么办?会影响MQ的使用,所以使用failover协议,第一个broker挂了可以直接使用第二个broker,但是前提是randomize的值必须是true。
(2)randomize的值必须是true,因为虽然使用了failover协议,但是如果第一个broker挂了,就不会使用第二个broker,因为randomize的值是false,但是如果改为true,就会自动使用第二个broker了。当randomize的值是true的时候,如果两个broker都存在,消息就会随机的发送到两个broker上。
从今往后,我们java代码连接ActiveMQ就推荐使用这种协议。
连接MQ的时候用randomize实现了broker的负载均衡,以后介绍消费者的负载均衡。
(2)动态连接方式