RabbitMQ的MTQQ插件实现即时通讯

rabbitMQ 同时被 2 个专栏收录
4 篇文章 0 订阅
1 篇文章 0 订阅

RabbitMQ的MTQQ插件实现即时通讯

MQTT协议
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的轻量级通讯协议,该协议构建于TCP/IP协议上。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。
MQTT相关概念
Publisher(发布者):消息的发出者,负责发送消息。
Subscriber(订阅者):消息的订阅者,负责接收并处理消息。
Broker(代理):消息代理,位于消息发布者和订阅者之间,各类支持MQTT协议的消息中间件都可以充当。
Topic(主题):可以理解为消息队列中的路由,订阅者订阅了主题之后,就可以收到发送到该主题的消息。
Payload(负载);可以理解为发送消息的内容。
QoS(消息质量):全称Quality of Service,即消息的发送质量,主要有QoS 0、QoS 1、QoS 2三个等级,下面分别介绍下:
QoS 0(Almost Once):至多一次,只发送一次,会发生消息丢失或重复;
QoS 1(Atleast Once):至少一次,确保消息到达,但消息重复可能会发生;
QoS 2(Exactly Once):只有一次,确保消息只到达一次。
启用MQTT
需要先安装RabbitMQ,这里就不做介绍了,百度安装教程即可
启用RabbitMQ的MQTT插件了,默认是不启用的,在RabbitMQ的安装目录下的sbin目录里在地址栏输入cmd并回车启动命令行,使用如下命令开启即可;

rabbitmq-plugins enable rabbitmq_mqtt

开启成功后查看管理控制台,我们可以发现MQTT服务运行在1883端口上了。
记得重启rabbitmq-service
在这里插入图片描述
MQTT客户端
这里我们使用的是MQTTBox,首先下载并安装好MQTTBox,下载地址:http://workswithweb.com/mqttbox.html
点击Create MQTT Client按钮来创建一个MQTT客户端;
在这里插入图片描述
接下来对MQTT客户端进行配置,主要是配置好协议端口、连接用户名密码和QoS即可;
在这里插入图片描述
再配置一个订阅者,订阅者订阅demoTopicA这个主题,我们会向这个主题发送消息;
配置好之后点击Subscribe
在这里插入图片描述
点击Publish发送消息,客端收到消息
在这里插入图片描述
前端直接实现即时通讯
既然MQTTBox客户端可以直接通过RabbitMQ实现即时通讯,我将通过html+javascript实现一个简单的聊天功能,真正不写一行后端代码实现即时通讯!
由于RabbitMQ与Web端交互底层使用的是WebSocket,所以我们需要开启RabbitMQ的MQTT WEB支持,使用如下命令开启即可;

rabbitmq-plugins enable rabbitmq_web_mqtt

开启成功后,查看管理控制台,我们可以发现MQTT的WEB服务运行在15675端口上了;
在这里插入图片描述
WEB端与MQTT服务进行通讯需要使用一个叫MQTT.js的库,项目地址:https://github.com/mqttjs/MQTT.js
接下来我们订阅不同的主题开启两个页面测试下功能(页面放在了SpringBoot应用的resource目录下了,需要先启动应用再访问):
在这里插入图片描述
在这里插入图片描述
在SpringBoot中使用
没有特殊业务需求的时候,前端可以直接和RabbitMQ对接实现即时通讯。但是有时候我们需要通过服务端去通知前端,此时就需要在应用中集成MQTT了

在pom.xml中添加MQTT相关依赖;

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

在application.yml中添加MQTT相关配置,主要是访问地址、用户名密码、默认主题信息;

rabbitmq:
  mqtt:
    url: tcp://localhost:1883
    username: guest
    password: guest
    defaultTopic: demoTopic

编写一个Java配置类从配置文件中读取配置便于使用;

@Data
@EqualsAndHashCode(callSuper = false)
@Component
@ConfigurationProperties(prefix = "rabbitmq.mqtt")
public class MqttConfig {
    /**
     * RabbitMQ连接用户名
     */
    private String username;
    /**
     * RabbitMQ连接密码
     */
    private String password;
    /**
     * RabbitMQ的MQTT默认topic
     */
    private String defaultTopic;
    /**
     * RabbitMQ的MQTT连接地址
     */
    private String url;
}

添加MQTT消息订阅者相关配置,使用@ServiceActivator注解声明一个服务激活器,通过MessageHandler来处理订阅消息;

@Slf4j
@Configuration
public class MqttInboundConfig {
    @Autowired
    private MqttConfig mqttConfig;

    @Bean
    public MessageChannel mqttInputChannel() {
        return new DirectChannel();
    }

    @Bean
    public MessageProducer inbound() {
        MqttPahoMessageDrivenChannelAdapter adapter =
                new MqttPahoMessageDrivenChannelAdapter(mqttConfig.getUrl(), "subscriberClient",
                        mqttConfig.getDefaultTopic());
        adapter.setCompletionTimeout(5000);
        adapter.setConverter(new DefaultPahoMessageConverter());
        //设置消息质量:0->至多一次;1->至少一次;2->只有一次
        adapter.setQos(1);
        adapter.setOutputChannel(mqttInputChannel());
        return adapter;
    }

    @Bean
    @ServiceActivator(inputChannel = "mqttInputChannel")
    public MessageHandler handler() {
        return new MessageHandler() {

            @Override
            public void handleMessage(Message<?> message) throws MessagingException {
                //处理订阅消息
                log.info("handleMessage : {}",message.getPayload());
            }

        };
    }
}

添加MQTT消息发布者相关配置;

@Configuration
public class MqttOutboundConfig {

    @Autowired
    private MqttConfig mqttConfig;

    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        MqttConnectOptions options = new MqttConnectOptions();
        options.setServerURIs(new String[] { mqttConfig.getUrl()});
        options.setUserName(mqttConfig.getUsername());
        options.setPassword(mqttConfig.getPassword().toCharArray());
        factory.setConnectionOptions(options);
        return factory;
    }

    @Bean
    @ServiceActivator(inputChannel = "mqttOutboundChannel")
    public MessageHandler mqttOutbound() {
        MqttPahoMessageHandler messageHandler =
                new MqttPahoMessageHandler("publisherClient", mqttClientFactory());
        messageHandler.setAsync(true);
        messageHandler.setDefaultTopic(mqttConfig.getDefaultTopic());
        return messageHandler;
    }

    @Bean
    public MessageChannel mqttOutboundChannel() {
        return new DirectChannel();
    }
}

添加MQTT网关,用于向主题中发送消息;

@Component
@MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
public interface MqttGateway {
    /**
     * 发送消息到默认topic
     */
    void sendToMqtt(String payload);

    /**
     * 发送消息到指定topic
     */
    void sendToMqtt(String payload, @Header(MqttHeaders.TOPIC) String topic);

    /**
     * 发送消息到指定topic并设置QOS
     */
    void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload);
}

添加MQTT测试接口,使用MQTT网关向特定主题中发送消息;

@RestController
@RequestMapping("/mqtt")
public class MqttController {

    @Autowired
    private MqttGateway mqttGateway;

    /**
     * 向默认主题发送消息
     * @param payload
     * @return
     */
    @PostMapping("/sendToDefaultTopic")
    public CommonResult sendToDefaultTopic(String payload) {
        System.out.println("payload:"+payload);
        mqttGateway.sendToMqtt(payload);
        return CommonResult.success(null);
    }

    /**
     * 向指定主题发送消息
     * @param payload
     * @param topic
     * @return
     */
    @PostMapping("/sendToTopic")
    public CommonResult sendToTopic(String payload, String topic) {
        mqttGateway.sendToMqtt(payload, topic);
        return CommonResult.success(null);
    }
}

postman测试
在这里插入图片描述

后台接收消息打印在这里插入图片描述

消息中间件应用越来越广泛,不仅可以实现可靠的异步通信,还可以实现即时通讯,掌握一个消息中间件还是很有必要的。如果没有特殊业务需求,客户端或者前端直接使用MQTT对接消息中间件即可实现即时通讯,有特殊需求的时候也可以使用SpringBoot集成MQTT的方式来实现,总之消息中间件是实现即时通讯的一个好选择!

  • 1
    点赞
  • 0
    评论
  • 6
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 1024 设计师:白松林 返回首页

打赏作者

会比心的狸花猫

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值