基于activeMQ broker cluster 集群 的高可用 多协议 物联网消息的架构设计

[size=large]
activeMQ是一款功能十分强大的消息中间件。
支持包括MQTT NIO 在内的多种协议,而且是jms的完美实现。当有数以百万计的终端设备需要连接到服务器时,适当处理和架构就可以对外提供功能强劲的服务能力。

首先需要解决activeMQ 单节点服务性能问题,切不可直接使用默认配置上生产。
可以自己百度 或者 参照 日志
http://m.blog.csdn.net/truong/article/details/73718621
http://blog.csdn.net/yinwenjie/article/details/50955502
http://blog.csdn.net/yinwenjie/article/details/50991443
http://blog.csdn.net/yinwenjie/article/details/51064242

单节点完成 则进行 集群搭建 一样参照博文
http://www.cnblogs.com/leihenqianshang/articles/5623858.html

搭建完成之后,高性能的服务架构已经出来了。这时候需要写一些测试代码。

[/size]

[size=large]
1 先写针对客户端和消费端都基于activeMQ API 的情况。生产者代码如下:
[/size]


package com.sunshine.mq;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;

import org.apache.activemq.ActiveMQConnectionFactory;

public class Producer {

public static void main(String[] args) throws JMSException {
// 连接到ActiveMQ服务器
//ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.15:61616)");
//这里可以使用 failover 机制 进行多节点配置 达到高可用和后端负载均衡
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.15:1883)");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 创建主题
Topic topic = session.createTopic("VirtualTopic.virtual-T.100990");
MessageProducer producer = session.createProducer(topic);
// NON_PERSISTENT 非持久化 PERSISTENT 持久化,发送消息时用使用持久模式
//producer.setDeliveryMode(DeliveryMode.PERSISTENT);
TextMessage message = session.createTextMessage();
for(int i = 0;i<10;i++){
message.setText("topic 消息。"+i);
message.setStringProperty("property", "消息Property");
// 发布主题消息
producer.send(message);
System.out.println("Sent message: " + message.getText());
}

session.close();
connection.close();
}
}


[size=large]
我们需要多个消费者来消费消息以达到 分布式部署的目的
消费者1
[/size]


package com.sunshine.mq;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;



import org.apache.activemq.ActiveMQConnectionFactory;

public class ConsumerA {

public static void main(String[] args) throws JMSException, InterruptedException {
// 连接到ActiveMQ服务器
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:1888,tcp://172.16.7.18:1889)");
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.15:1887)");
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:61616,tcp://172.16.7.18:61616)");
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:1883,tcp://172.16.7.18:1883)");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 创建主题
Queue topicA = session.createQueue("Consumer.GG.VirtualTopic.virtual-T.*");
// 消费者A组创建订阅
MessageConsumer consumerA1 = session.createConsumer(topicA);
Integer count = 0;
while(true){
Message message = consumerA1.receive();
count++;
TextMessage msg = (TextMessage)message;
final String messageText = msg.getText();
System.out.println(messageText +",消费消息总数为:"+count);
}
/**consumerA1.setMessageListener(new MessageListener() {
// 订阅接收方法
public void onMessage(Message message) {
TextMessage tm = (TextMessage) message;
try {
System.out.println("A 收到消息: " + tm.getText()+":"+tm.getStringProperty("property"));
} catch (JMSException e) {
e.printStackTrace();
}
}
});**/

//session.close();
//connection.close();
}
}


[size=large]消费者2 [/size]


package com.sunshine.mq;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

public class ConsumerB {

public static void main(String[] args) throws JMSException, InterruptedException {
// 连接到ActiveMQ服务器
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(nio://172.16.7.17:1888,nio://172.16.7.18:1889)");
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:61616,tcp://172.16.7.18:61616)");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 创建主题
Queue topicA = session.createQueue("Consumer.GG.VirtualTopic.virtual-T.*");
// 消费者A组创建订阅
MessageConsumer consumerA1 = session.createConsumer(topicA);
Integer count = 0;
while(true){
Message message = consumerA1.receive();
count++;
TextMessage msg = (TextMessage)message;
final String messageText = msg.getText();
System.out.println(messageText +",消费消息总数为:"+count);

}
/**consumerA1.setMessageListener(new MessageListener() {
// 订阅接收方法
public void onMessage(Message message) {
TextMessage tm = (TextMessage) message;
try {
System.out.println("B 收到消息: " + tm.getText()+":"+tm.getStringProperty("property"));
} catch (JMSException e) {
e.printStackTrace();
}
}
});**/
//session.close();
//connection.close();
}
}


[size=large]消费者3[/size]


package com.sunshine.mq;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;

public class ConsumerC {

public static void main(String[] args) throws JMSException, InterruptedException {
// 连接到ActiveMQ服务器
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(nio://172.16.7.17:1888,nio://172.16.7.18:1889)");
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:61616,tcp://172.16.7.18:61616)");
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(mqtt://172.16.7.17:1883,mqtt://172.16.7.18:1883)");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 创建主题
Queue topicA = session.createQueue("Consumer.GG.VirtualTopic.virtual-T.*");
// 消费者A组创建订阅
MessageConsumer consumerA1 = session.createConsumer(topicA);
Integer count = 0;
while(true){
Message message = consumerA1.receive();
count++;
TextMessage msg = (TextMessage)message;
final String messageText = msg.getText();
System.out.println(messageText +",消费消息总数为:"+count);

}
/**consumerA1.setMessageListener(new MessageListener() {
// 订阅接收方法
public void onMessage(Message message) {
TextMessage tm = (TextMessage) message;
try {
System.out.println("B 收到消息: " + tm.getText()+":"+tm.getStringProperty("property"));
} catch (JMSException e) {
e.printStackTrace();
}
}
});**/
//session.close();
//connection.close();
}
}


[size=large]
测试的结果是 生产者生成的消息会负载到不同的消费者客户端,各个消费者客户端消费了不同的消息。这里不管生产者生产的消息是走队列还是走topic 其结果都是实现了消息的路由。

假设出现一种情况,设备端只支持MQTT协议,使用了MQTTClient 发送消息或者只想走MQTT,那么针对这个架构该如何应对呢?道理是一样的,由于linux-c或者C++ 客户端开发人员的尿性,所以 生产者模拟程序
[/size]


package com.sunshine.mqtt;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;


public class MyMqttClient {
private String host="tcp://172.16.7.15:1887";
private String userName="admin";
private String passWord = "activemq.123";
private MqttConnectOptions options;
private MqttClient client;
private MqttMessage message ;
private String[] myTopics={"test_result/20179112982783"};
private int[] myQos={2};
private MqttTopic topic;
private String myTopic = "test/20179112982783";
public MyMqttClient(){
try {
client=new MqttClient(host,"test99990000",new MemoryPersistence());
options = new MqttConnectOptions();
options.setCleanSession(false);
options.setUserName(userName);
options.setPassword(passWord.toCharArray());
options.setConnectionTimeout(10);
options.setKeepAliveInterval(20);
client.setCallback(new MqttCallback(){

@Override
public void connectionLost(Throwable cause) {

}

@Override
public void messageArrived(String topicName, MqttMessage message)
throws Exception {
System.out.println("topicName is :"+topicName);
System.out.println("Message is:"+message.toString());
}

@Override
public void deliveryComplete(IMqttDeliveryToken token) {

}});

client.connect(options);
client.subscribe(myTopics,myQos);

} catch (Exception e) {
e.printStackTrace();
}
}

public void sendMessage(String topicT,String messageTest){
try {
message = new MqttMessage();
message.setQos(0);
message.setRetained(true);
message.setPayload(messageTest.getBytes());
topic = client.getTopic(topicT);
MqttDeliveryToken token = topic.publish(message);
token.waitForCompletion();
System.out.println(" 发送消息:"+messageTest);
} catch (Exception e) {
e.printStackTrace();
}
}
}




package com.sunshine.mqtt;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.junit.Test;


public class MyMqttTest {

@Test
public void testMQTT(){
MyMqtt mqtt = new MyMqtt();
mqtt.sendMessage("我向客户端发送了一条消息");
}

@Test
public void testMQTTClient(){
MyMqttClient client=new MyMqttClient();
//client.sendMessage("我向服务端发送了一条消息,我的SN是 20179112982783");
}

@Test
public void testIotConnect() throws InterruptedException{
MyMqttClient client=new MyMqttClient();
for(int i=0;i<10;i++){
client.sendMessage("VirtualTopic/100990"+i,"mqtt-msg:"+i+">"+("100990"+i));
}
}
}




[size=large]三个消费者[/size]


package com.sunshine.mq;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.TopicConnectionFactory;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQBytesMessage;

public class ConsumerTopicA {

public static void main(String[] args) throws JMSException, InterruptedException {
// 连接到ActiveMQ服务器
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:1888,tcp://172.16.7.18:1889)");
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.15:1887)");
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:61616,tcp://172.16.7.18:61616)");
//ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:1883,tcp://172.16.7.18:1883)");
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin", "failover:(tcp://172.16.7.17:1888,tcp://172.16.7.18:1889)");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 创建主题
Queue topicA = session.createQueue("Consumer.GG.VirtualTopic.*");
// 消费者A组创建订阅
MessageConsumer consumerA1 = session.createConsumer(topicA);
Integer count = 0;
while(true){
//在实际生产过程中不建议使用receive 会造成阻塞并损耗大量资源 建议直接使用spring jms 监听器
ActiveMQBytesMessage message = (ActiveMQBytesMessage) consumerA1.receive();
count++;
// TextMessage msg = (TextMessage)message;
// String messageText = msg.getText();
System.out.println(new String(message.getMessage().getContent().getData()) +",消费消息总数为:"+count);
}
/**consumerA1.setMessageListener(new MessageListener() {
// 订阅接收方法
public void onMessage(Message message) {
TextMessage tm = (TextMessage) message;
try {
System.out.println("A 收到消息: " + tm.getText()+":"+tm.getStringProperty("property"));
} catch (JMSException e) {
e.printStackTrace();
}
}
});**/

//session.close();
//connection.close();
}
}





package com.sunshine.mq;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.TopicConnectionFactory;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQBytesMessage;

public class ConsumerTopicB {

public static void main(String[] args) throws JMSException, InterruptedException {
// 连接到ActiveMQ服务器
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:1888,tcp://172.16.7.18:1889)");
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.15:1887)");
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:61616,tcp://172.16.7.18:61616)");
//ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:1883,tcp://172.16.7.18:1883)");
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin", "failover:(tcp://172.16.7.17:1888,tcp://172.16.7.18:1889)");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 创建主题
Queue topicA = session.createQueue("Consumer.GG.VirtualTopic.*");
// 消费者A组创建订阅
MessageConsumer consumerA1 = session.createConsumer(topicA);
Integer count = 0;
while(true){
ActiveMQBytesMessage message = (ActiveMQBytesMessage) consumerA1.receive();
count++;
// TextMessage msg = (TextMessage)message;
// String messageText = msg.getText();
System.out.println(new String(message.getMessage().getContent().getData()) +",消费消息总数为:"+count);
}
/**consumerA1.setMessageListener(new MessageListener() {
// 订阅接收方法
public void onMessage(Message message) {
TextMessage tm = (TextMessage) message;
try {
System.out.println("A 收到消息: " + tm.getText()+":"+tm.getStringProperty("property"));
} catch (JMSException e) {
e.printStackTrace();
}
}
});**/

//session.close();
//connection.close();
}
}



package com.sunshine.mq;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.TopicConnectionFactory;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQBytesMessage;

public class ConsumerTopicC {

public static void main(String[] args) throws JMSException, InterruptedException {
// 连接到ActiveMQ服务器
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:1888,tcp://172.16.7.18:1889)");
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.15:1887)");
// ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:61616,tcp://172.16.7.18:61616)");
//ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin","failover:(tcp://172.16.7.17:1883,tcp://172.16.7.18:1883)");
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("admin", "admin", "failover:(tcp://172.16.7.17:1888,tcp://172.16.7.18:1889)");
Connection connection = factory.createConnection();
connection.start();
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
// 创建主题
Queue topicA = session.createQueue("Consumer.GG.VirtualTopic.*");
// 消费者A组创建订阅
MessageConsumer consumerA1 = session.createConsumer(topicA);
Integer count = 0;
while(true){
ActiveMQBytesMessage message = (ActiveMQBytesMessage) consumerA1.receive();
count++;
// TextMessage msg = (TextMessage)message;
// String messageText = msg.getText();
System.out.println(new String(message.getMessage().getContent().getData()) +",消费消息总数为:"+count);
}
/**consumerA1.setMessageListener(new MessageListener() {
// 订阅接收方法
public void onMessage(Message message) {
TextMessage tm = (TextMessage) message;
try {
System.out.println("A 收到消息: " + tm.getText()+":"+tm.getStringProperty("property"));
} catch (JMSException e) {
e.printStackTrace();
}
}
});**/

//session.close();
//connection.close();
}
}



[size=large]
此时客户端只支持单个broker地址,可以通过一些策略分配给客户端相对比较空闲的broker
[/size]
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

annan211

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值