Linux安装Rabbit MQ

一、下载安装包

erlang-23.3.4.8-1.el7.x86_64.rpm

rabbitmq-server-3.9.11-1.el7.noarch.rpm

二、linux 环境

centos7

三、安装

1、erlang

rpm -Uvh erlang-23.3.4.8-1.el7.x86_64.rpm

2、安装RabbitMq

rpm rabbitmq-server-3.9.11-1.el7.noarch.rpm

注:如果是tar.gz的包可能需要socat插件环境

3、启动RabbitMq

service rabbitmq-server start
service rabbitmq-server stop
service rabbitmq-server status

4、创建admin用户

rabbitmqctl add_user admin admin

rabbitmqctl set_user_tags admin administrator

5、开启1883端口

rabbitmq-plugins enable rabbitmq_mqtt

6、安装过程中遇到的问题:

当页面访问guest用户时,不能登录,只能localhost:15762登录
解决办法:去修改rabbitmq.app配置文件
没找到,新增了用户,删除了guest,使用新用户登录即可

四、springboot集成使用

1、yml环境

mqtt:
  service_name: dataServe2
  url: tcp://121.199.166.81:1883 # MQTT 1883固定
  #url: tcp://192.168.1.243:1883 # MQTT 1883固定
  username: admin #rabbitMq 账号
  password: admin #rabbitMq 密码

2、mqtt pom依赖

<!-- 引入 mqtt 相关依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-integration</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-stream</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-mqtt</artifactId>
</dependency>

3、配置类

import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Date;

@Configuration
public class MqttConfig {

    private static final Logger log = LoggerFactory.getLogger(MqttConfig.class);
    @Value("${dataServe.mqtt.username}")
    private String username;

    @Value("${dataServe.mqtt.password}")
    private String password;

    @Value("${dataServe.mqtt.url}")
    private String hostUrl;

    @Value("${dataServe.mqtt.service_name}")
    private String serviceName;

    private MqttClient client;

    /**
     * 获取MqttClient
     * @return client
     */
    public MqttClient getMqttClient() throws MqttException{
        client = new MqttClient(hostUrl, serviceName, new MemoryPersistence());
        // 设置回调
        client.setCallback(new MqttCallBack());
        return client;
    }


    /**
     * 初始化
     */
    @PostConstruct
    public void init() {
        this.connect();
    }
    /**
     * 断开连接
     */
    @PreDestroy
    public void disConnect() {
        try {
            client.disconnect();
            log.info("与mqtt断开连接:{}", new Date());
            client.close();
        } catch (MqttException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 连接
     */
    private void connect() {
        try {
            // 创建MQTT客户端对象
            client = getMqttClient();
            // 连接设置
            MqttConnectOptions options = getMqttConnectOptions();
            // 设置遗嘱消息的话题,若客户端和服务器之间的连接意外断开,服务器将发布客户端的遗嘱信息
            options.setWill("willTopic", (serviceName + "与服务器断开连接").getBytes(), 0, false);
            // 连接
            client.connect(options);
            log.info("与mqtt建立连接:{}",new Date());
            // 订阅主题 (接受此主题的消息)
//            this.subscribe("warn_topic", 2);
        } catch (MqttException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 连接设置
     * @return MqttConnectOptions
     */
    private MqttConnectOptions getMqttConnectOptions() {
        MqttConnectOptions options = new MqttConnectOptions();
        // 是否清空session,设置false表示服务器会保留客户端的连接记录(订阅主题,qos),客户端重连之后能获取到服务器在客户端断开连接期间推送的消息
        // 设置为true表示每次连接服务器都是以新的身份
        //options.setCleanSession(true);
        // 设置连接用户名
        options.setUserName(username);
        options.setAutomaticReconnect(true);
        //断链后是否清除session
        options.setCleanSession(false);
        // 设置连接密码
        options.setPassword(password.toCharArray());
        // 设置超时时间,单位为秒
        options.setConnectionTimeout(100);
        // 设置心跳时间 单位为秒,表示服务器每隔 1.5*20秒的时间向客户端发送心跳判断客户端是否在线
        options.setKeepAliveInterval(20);
        return options;
    }
    /**
     * 发布消息
     *
     * @param topic 主题
     * @param message 消息
     */
    public boolean publish(String topic, String message) {
        MqttMessage mqttMessage = new MqttMessage();
        // 0:最多交付一次,可能丢失消息
        // 1:至少交付一次,可能消息重复
        // 2:只交付一次,既不丢失也不重复
        mqttMessage.setQos(2);
        // 是否保留最后一条消息
        mqttMessage.setRetained(false);
        // 消息内容
        mqttMessage.setPayload(message.getBytes());
        // 主题的目的地,用于发布/订阅信息
        MqttTopic mqttTopic = client.getTopic(topic);
        // 提供一种机制来跟踪消息的传递进度
        // 用于在以非阻塞方式(在后台运行)执行发布是跟踪消息的传递进度
        MqttDeliveryToken token;
        try {
            // 将指定消息发布到主题,但不等待消息传递完成,返回的token可用于跟踪消息的传递状态
            // 一旦此方法干净地返回,消息就已被客户端接受发布,当连接可用,将在后台完成消息传递。
            token = mqttTopic.publish(mqttMessage);
            token.waitForCompletion();
            return true;
        } catch (MqttException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 订阅主题
     */
    public void subscribe(String topic, int qos) {
        try {
            client.setCallback(new MqttCallBack());
            client.subscribe(topic, qos);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}

4、回调方法

import org.eclipse.paho.client.mqttv3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.Date;
public class MqttCallBack implements MqttCallback {
    private static final Logger log = LoggerFactory.getLogger(MqttCallBack.class);

    /**
     * 连接丢失操作,可手动重连 或option配置自动连接
     * @param cause the reason behind the loss of connection.
     */
    @Override
    public void connectionLost(Throwable cause) {

//        try {
//            if (client != null && !client.isConnected()) {
//                log.info("正在尝试重连mqtt:{}", new Date());
//                client.reconnect();
//            } else {
//                log.info("mqtt正在建立新连接:{}", new Date());
//                client.connect();
//            }
//        } catch (MqttException e) {
//            throw new RuntimeException(e);
//        }
        log.error("mqtt与服务断开连接:{}", new Date());
    }

    /**
     * 收到消息的处理
     * @param topic the topic on which the message was received.
     * @param message the received message.
     * @throws Exception 异常
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        log.info("【发送】消息主题:【{}】", topic);
        log.info("【发送】消息Qos:【{}】", message.getQos());
        log.info("【发送】消息内容:【{}】", new String(message.getPayload()));
        log.info("【发送】消息retained:【{}】", message.isRetained());
    }
    /**
     * 消息发布完成
     * @param token the token for the publish that has completed.
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        IMqttAsyncClient client = token.getClient();
        log.info("【发送】【{}】##########发布消息成功!", client.getClientId());
    }
}

5、调用

boolean publish = mqttConfig.publish("mqtt-subscription-dataServe", result.toString());
//订阅subscribe函数

6、java 连接mqtt产生的问题

clientId 必须唯一,两个相同的id会导致重复断链