最近在公司技术沙龙上面,有同事分享了一个push消息中间件,出于兴趣愿意,自己就做了一番研究整理,希望能给有需要的朋友带来一些帮助。
几个名词解释:
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议
MQTT Broker:Moquette 是 Java 的 MQTT 代理实现,支持 QoS 0,QoS 1 和 QoS 2。Moquette 设计为事件,使用 Netty 作为协议编码和解码,协议逻辑本质上是单线程,并且通过 LMAX disruptor 的循环缓冲器独立于前端连接器部分。源码下载:https://github.com/andsel/moquette
MQTT Client : MQTT有不同语言,不同版本的诸多的,其中Eclipse Paho只是诸多Java实现中的一个,Eclipse Paho的介绍如下的http://www.eclipse.org/paho/,具体下载地址https://github.com/eclipse/paho.mqtt.java
Moquette源码下来以后需要编译成Jar,才可以使用,或者直接copy源代码,执行server main方法即可
Broker启动代码:
之前一直没明白消息中间件的原理,在Broker,Server,Client,Publisher,Subscriber混淆不清,现在理解的是,严格意义上来说,消息中间件是不存在绝对的server端和client端,消息订阅者和消息发布者可以随时互换角色,只要有订阅某个topic即可,Broker作为消息的中转通道,所做的事情,简单来说就是把消息发布者发布的消息转发到消息订阅者,当然涉及类似订阅主题,长链心跳时间等等,都是在Broker实现的。package io.moquette.broker;
import io.moquette.server.Server;
import io.moquette.server.config.IConfig;
import io.moquette.server.config.MemoryConfig;
import java.io.IOException;
import java.util.Properties;
public class Broker {
Server m_server;
IConfig m_config;
public static void main(String[] args) {
Broker b = new Broker();
b.startServer();
}
private void startServer() {
m_server = new Server();
final Properties configProps = IntegrationUtils.prepareTestProperties();
m_config = new MemoryConfig(configProps);
try {
m_server.startServer(m_config);
System.out.println("moquette broker is starting ......");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client之消息订阅者:
package org.eclipse.paho.bamboohat;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
public class MQTTSubscriber {
public static String doTest(int i) {
try {
// 创建MqttClient
MqttClient client = new MqttClient(Configuration.TCPAddress, "scriber");
// 回调处理类
SubCallBack callback = new SubCallBack("scriber", i);
client.setCallback(callback);
// 创建连接可选项信息
MqttConnectOptions conOptions = new MqttConnectOptions();
conOptions.setCleanSession(Configuration.cleanSession);
conOptions.setKeepAliveInterval(Configuration.keepAliveInterval);
// 连接broker
client.connect(conOptions);
// 发布相关的订阅
client.subscribe(Configuration.topic, Configuration.QoS);
Scanner scan = new Scanner(System.in);
for (String input = ""; !input.equalsIgnoreCase("q"); input = scan.nextLine()) ;
client.disconnect();
System.out.println("Finished");
} catch (Exception e) {
e.printStackTrace();
return "failed";
}
return "success";
}
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
for(int i=0;i<1;i++){
MyTask myTask = new MyTask(i);
executor.execute(myTask);
}
}
}
class MyTask implements Runnable {
private int i;
public MyTask() {
super();
}
public MyTask(int i) {
super();
this.i = i;
}
@Override
public void run() {
MQTTSub sub = new MQTTSub();
sub.doTest(i);
}
}
Client之消息发布者:
package org.eclipse.paho.bamboohat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttTopic;
public class MQTTPublisher {
public static void doTest() {
try {
MqttClient client = new MqttClient("tcp://localhost:1883", "mqttserver-pub");
MqttTopic topic = client.getTopic(Configuration.topic);
// MqttMessage message = new
// MqttMessage("Hello World. Hello IBM".getBytes());
// message.setQos(1);
client.connect();
MqttMessage message = null;
for (int i = 10; i < 20; i++) {
message = new MqttMessage(("This is message " + i + ", hello!").getBytes());
message.setQos(1);
MqttDeliveryToken token = topic.publish(message);
while (!token.isComplete()) {
token.waitForCompletion(1000);
}
}
client.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
try {
MqttClient client = new MqttClient(Configuration.TCPAddress, "publisher");
client.connect();
MqttTopic topic = client.getTopic(Configuration.topic);
BufferedReader br = null;
new BufferedReader(new InputStreamReader(System.in));
String message = "You don't publish any message!";
while (true) {
System.out.print("请输入待发布信息:");
br = new BufferedReader(new InputStreamReader(System.in));
String m = br.readLine();
if (m != null && !m.trim().equals("")) {
message = m;
}
MqttMessage _m = new MqttMessage(message.getBytes("utf8"));
_m.setQos(Configuration.QoS);
MqttDeliveryToken token = topic.publish(_m);
token.waitForCompletion(Configuration.sleepTimeout);
System.out.println("Delivery token " + token.hashCode() + " has been received : " + token.isComplete());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}