以debain系统作为本次测试系统。
安装emqtt:http://emqtt.com/downloads 下载对应版本的emqtt包
常用命令:
# 启动emqttd
./bin/emqttd start
# 检查运行状态
./bin/emqttd_ctl status
# 停止emqttd
./bin/emqttd stop
emqtt控制台地址: http://127.0.0.1:18083,默认用户: admin,密码:public
这里主要介绍emqtt集群与haproxy做tcp负载均衡的使用,其它emqtt文档详见官方文档http://emqtt.com/docs/v2/getstarted.html
EMQ 默认开启的 MQTT 服务 TCP 端口:
1883 MQTT 协议端口
8883 MQTT/SSL 端口
8083 MQTT/WebSocket 端口
8084 MQTT/WebSocket/SSL 端口
防火墙根据使用的 MQTT 接入方式,开启上述端口的访问权限。
EMQ 节点集群使用的 TCP 端口:
4369 集群节点发现端口
6369 集群节点控制通道
集群节点间如有防护墙,需开启上述 TCP 端口互访权限。
目前三台虚拟机:192.168.10.12(负载均衡服务器) 192.168.10.14 (emq服务器1) 192.168.10.17(emq服务器2)
集群配置如下:
1、启动emqtt: 进入emq的bin目录执行命令:./emqttd start 两台服务器emq皆启动
2、eqm节点设置:emq.conf配置文件
## Node name
#node.name = emq@127.0.0.1
node.name = emq@192.168.10.17
另一台14服务器配置相同,仅ip地址不同,配置完成后重启emq
3、节点加入集群在14服务器上执行(也可在17服务器上执行):$ ./bin/emqttd_ctl cluster join emq@192.168.10.17
执行完成后查看:$ ./bin/emqttd_ctl cluster status
显示如下:
集群成功,结点退出集群命令如下:
本节点退出集群:$ ./bin/emqttd_ctl cluster leave
删除其它节点:$ ./bin/emqttd_ctl cluster remove emq@192.168.10.17
至此emq集群完成。
HAProxy是一个使用C语言编写的自由及开放源代码软件,其提供高可用性、负载均衡,以及基于TCP和HTTP的应用程序代理。
HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在当前的硬件上,完全可以支持数以万计的并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中, 同时可以保护你的web服务器不被暴露到网络上。当然最大的好处就是免费。
12服务器上使用apt安装haproxy: apt-get intall haproxy 。也可以使用源码安装,这里偷个懒
haproxy常用命令如下:
1、启动 service haproxy start
2、关闭 service haproxy stop
3、重启 service haproxy restart
安装完成后haproxy的配置文件路径:/etc/haproxy/haproxy.cfg
编辑haproxy.cfg ,打开haproxy后台管理统计功能。
listen stats
bind 0.0.0.0:9080
mode http
option httplog
maxconn 10
stats refresh 30s
stats uri /stats
stats realm Haproxy Manager
stats auth user:user
stats hide-version
stats admin if TRUE
访问:192.168.10.12:9080/stats 进入后台管理系统。
为eqmtt配置tcp负载均衡:
listen mqtt
bind *:8883 no-sslv3
mode tcp
maxconn 50000
balance source
timeout client 50000
timeout server 50000
##balance roundrobin
server emq1 192.168.10.14:1883 check inter 10000 fall 2 rise 5 weight 1
server emq2 192.168.10.17:1883 check inter 10000 fall 2 rise 5 weight 1
至此配置完成,通过tcp访问192.168.10.12:8883即可发布订阅消息。
也可以为emqtt后台管理系统配置负载均衡如下:
listen mqtt-admin-front
bind *:18083
mode http
default_backend emqtt-admin-backend
backend emqtt-admin-backend
balance roundrobin
server emq_web1 192.168.10.14:18083 check
server emq_web2 192.168.10.17:18083 check
或者:
listen mqtt-admin-front
bind *:18083
mode http
balance roundrobin
server emq_web1 192.168.10.14:18083 check
server emq_web2 192.168.10.17:18083 check
配置完成后重启haproxy。
以下为java通过mqtt发布订阅消息代码。
引入jar包
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.0</version>
</dependency>
客户端代码:
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
public class App1 {
public static void main(String[] args) {
String topic = "MQ/1/#";
int qos = 2;
String broker = "tcp://192.168.10.12:8883";
String clientId = "MQTTWS2";
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
System.out.println("server Connecting to broker: " + broker);
sampleClient.connect(connOpts);
sampleClient.subscribe(topic, qos);
sampleClient.setCallback(new MyMqttCallBack());
System.out.println("server Connected");
} catch (MqttException me) {
System.out.println("reason " + me.getReasonCode());
System.out.println("msg " + me.getMessage());
System.out.println("loc " + me.getLocalizedMessage());
System.out.println("cause " + me.getCause());
System.out.println("excep " + me);
me.printStackTrace();
}
}
}
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
public class MyMqttCallBack implements MqttCallback {
public void connectionLost(Throwable cause) {
// TODO Auto-generated method stub
}
public void messageArrived(String topic, MqttMessage message) throws Exception {
// TODO Auto-generated method stub
System.out.println("receive message :"+new String(message.getPayload()));
}
public void deliveryComplete(IMqttDeliveryToken token) {
// TODO Auto-generated method stub
}
}
消息发送代码如下:
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.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
public class App {
public static void main(String[] args) {
String topic = "MQ/1/a";
String content = "Message from MqttPublishSample";
int qos = 2;
String broker = "tcp://192.168.10.12:8883";
String clientId = "MQTTWS";
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
System.out.println("Connecting to broker: " + broker);
sampleClient.connect(connOpts);
System.out.println("Connected");
for (int i = 0; i < 10; i++) {
content += (i + 1);
MqttMessage message = new MqttMessage(content.getBytes());
message.setQos(qos);
MqttTopic topic2 = sampleClient.getTopic(topic);
MqttDeliveryToken publish = topic2.publish(message);
publish.waitForCompletion();
Thread.sleep(1000L);
// sampleClient.publish(topic, message);
}
sampleClient.disconnect();
System.out.println("send message Disconnected");
System.exit(0);
} catch (MqttException me) {
System.out.println("reason " + me.getReasonCode());
System.out.println("msg " + me.getMessage());
System.out.println("loc " + me.getLocalizedMessage());
System.out.println("cause " + me.getCause());
System.out.println("excep " + me);
me.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
最后再说明一下官方文档上HAProxy -> EMQ 集群
本人使用官方文档配置导致haproxy启动失败,首先没有emq.pem这个文件,其次属性ssl crt也无法识别。这或许是个坑吧,暂时不深究原因,如果有朋友知道的也烦请告知一二。