订阅者模块

1. 客户端实现思路

在 RabbitMQ 中,提供服务的是信道,因此在客户端的实现中,弱化了 Client 客户端的概念,也就是说在 RabbitMQ 中并不会向用户展示网络通信的概念出来,而是以一种提供服务的形式来体现。

其实现思想类似于普通的功能接口封装,一个接口实现一个功能,接口内部完成向客户端请求的过程,但是对外并不需要体现出客户端与服务端通信的概念,用户需要什么服务就调用什么接口就行。

基于以上的思想,客户端的实现共分为四大模块:

  • 订阅者模块:
    • 一个并不直接对用户展示的模块,其在客户端体现的作用就是对于角色的描 述,表示这是一个消费者
  • 信道模块
    • 一个直接面向用户的模块,内部包含多个向外提供的服务接口,用户需要什么服务,调用对应接口即可○ 其包含交换机声明/删除,队列声明/删除,绑定/解绑,消息发布/确认,订阅/解除订阅等服务。
  • 连接模块
    • 这是唯一能体现出网络通信概念的一个模块了,它向用户提供的功能就是用于打开/关闭信道。
  • 异步线程模块
    • 虽然客户端部分,并不对外体现网络通信的概念,但是本质上内部还是包含有网络通信的,因此既然有网络通信,那么就必须包含有一个网络通信 IO 事件监控线程模块,用于进行客户端连接的 IO 事件监控,以便于在事件出发后进行 IO 操作。
    • 其次,在客户端部分存在一个情况就是,当一个信道作为消费者而存在的时 候,服务端会向信道推送消息,而用户这边需要对收到的消息进行不同的业务处理,而这个消息的处理需要一个异步的工作线程池来完成。
    • 因此异步线程模块包含两个部分:
      • 客户端连接的 IO 事件监控线程
      • 推送过来的消息异步处理线程

基于以上模块,实现一个客户端的流程也就比较简单了

  1. 实例化异步线程对象
  2. 实例化连接对象
  3. 通过连接对象,创建信道
  4. 根据信道获取自己所需服务
  5. 关闭信道
  6. 关闭连接

2. 订阅者模块

与服务端,并无太大差别,客户端这边虽然订阅者的存在感微弱了很多,但是还是有的,当进行队列消息订阅的时候,会伴随着一个订阅者对象的创建,而这个订阅者对象有以下几个作用:

  • 描述当前信道订阅了哪个队列的消息。
  • 描述了收到消息后该如何对这条消息进行处理。
  • 描述收到消息后是否需要进行确认回复。

所以,订阅者模块并不直接对用户展示,它是对消费者角色的描述。当用户通过信道订阅队列时,内部会创建一个订阅者对象,该对象负责处理从服务端推送过来的消息。

设计要点:

  1. 每个订阅者对应一个消费者标签(consumer_tag)和一个队列(queue_name)。
  2. 订阅者需要提供一个回调函数,当消息到达时,异步线程模块会调用这个回调函数。
  3. 订阅者可能支持自动确认或手动确认模式。

因此订阅者信息:

  • 订阅者标识
  • 订阅队列名
  • 是否自动确认标志
  • 回调处理函数(收到消息后该如何处理的回调函数对象)
cpp 复制代码
#ifndef __M_CONSUMER_H__
#define __M_CONSUMER_H__
#include "../mqcommon/logger.hpp"
#include "../mqcommon/helper.hpp"
#include "../mqcommon/msg.pb.h"
#include <iostream>
#include <unordered_map>
#include <mutex>
#include <memory>
#include <vector>
#include <functional>


namespace rabbitmq
{
    using ConsumerCallback = std::function<void(const std::string, const BasicProperties *bp, const std::string)>;
    struct Consumer
    {
        using ptr = std::shared_ptr<Consumer>;
        std::string _tag; //消费者标识
        std::string _qname; //消费者订阅的队列名称
        bool _auto_ack; //自动确认标志
        ConsumerCallback _callback;

        Consumer()
        {
            DLOG("new Consumer: %p", this);
        }
        Consumer(const std::string &ctag, const std::string &queue_name,  bool ack_flag, const ConsumerCallback &cb)
            :_tag(ctag), _qname(queue_name), _auto_ack(ack_flag), _callback(std::move(cb)) 
        {
            DLOG("new Consumer: %p", this);
        }
        ~Consumer() 
        {
            DLOG("del Consumer: %p", this);
        }
    };
}

#endif
相关推荐
William Dawson2 小时前
【实战分享】DTU设备高并发数据接入全流程(Redis + RabbitMQ + 数据库)
数据库·redis·rabbitmq
Albert Edison1 天前
【RabbitMQ】核心概念|工作流程|界面操作
分布式·rabbitmq·ruby
少许极端2 天前
消息队列5-RabbitMQ的高级特性和MQ的应用问题与解决方案-事务、消息分发的应用、幂等性保证、顺序性保证、消息积压的解决
分布式·消息队列·rabbitmq
Arva .2 天前
RabbitMQ
网络·分布式·rabbitmq
小江的记录本2 天前
【RabbitMQ】RabbitMQ核心知识体系全解(5大核心模块:Exchange类型、消息确认机制、死信队列、延迟队列、镜像队列)
java·前端·分布式·后端·spring·rabbitmq·mvc
fzb5QsS1p2 天前
Maomi.MQ 功能强大的 .NET RabbitMQ 消息队列通讯模型框架来了
rabbitmq·.net·ruby
zs宝来了3 天前
RabbitMQ 可靠性投递:持久化、确认机制与死信队列
rabbitmq·死信队列·持久化·可靠性·确认机制
BPM_宏天低代码4 天前
宏天CRM系统的消息中心:基于RabbitMQ的实践
分布式·rabbitmq
少许极端5 天前
消息队列4-RabbitMQ的高级特性-TTL机制、死信队列、延迟队列
分布式·消息队列·rabbitmq
014-code5 天前
RabbitMQ 生产端可靠投递(confirm、return、重试)
分布式·消息队列·rabbitmq