【消息队列项目】连接管理模块实现

目录

[一.Connection类 - 连接实例](#一.Connection类 - 连接实例)

[二 ConnectionManager类 - 连接集中管理](#二 ConnectionManager类 - 连接集中管理)

[三. 工作流程详解](#三. 工作流程详解)

四.代码总结

五.代码测试


本模块采用两级管理体系实现网络连接的高效管理。

  • 顶层为连接管理器(ConnectionManager),负责全局连接的注册与生命周期管理;
  • 底层为Connection连接对象(Connection),封装单个物理连接并提供逻辑信道的多路复用能力。

每个Connection对象基于Muduo网络库的TcpConnection实现,内置Protobuf协议编解码器、消费者管理器、虚拟机主机环境以及线程池资源,能够在一个物理连接上创建多个独立的逻辑信道,实现业务流隔离与资源复用。

一.Connection类 - 连接实例

职责:

管理单个TCP连接的完整生命周期,提供信道创建、关闭与检索功能,处理连接级别的协议交互。

核心成员:

  • 连接关联的信道管理句柄(实现信道的增删查)
  • 连接关联的实际用于通信的muduo::net::Connection连接
  • protobuf 协议处理的句柄(ProtobufCodec对象)
  • 消费者管理句柄:管理消息消费逻辑,将协议消息路由到对应的业务处理器
  • 虚拟机管理句柄:关联的虚拟主机实例,提供业务执行环境
  • 异步线程池句柄:用于执行耗时的业务处理任务,避免阻塞网络I/O线程

信道管理接口

  • openChannel():根据请求创建新信道,验证信道ID唯一性,初始化信道资源与回调,向客户端返回创建结果
  • closeChannel():关闭指定信道,清理信道相关资源,通知客户端关闭完成
  • getChannel():根据信道ID检索已建立的信道
  • basicResponse():生成标准响应消息,统一设置请求ID、信道ID和操作结果,通过协议编解码器发送至客户端

根据上述涉及,我们很快就能写出下面这个代码

cpp 复制代码
// Connection类:管理单个TCP连接,提供信道的创建、关闭和查询功能
class Connection { 
public: 
    using ptr = std::shared_ptr<Connection>;  // 智能指针别名,便于资源管理
    
    // 构造函数:初始化连接所需的各个组件
    Connection(const VirtualHost::ptr &host,       // 虚拟机主机环境
               const ConsumerManager::ptr &cmp,    // 消费者管理器
               const ProtobufCodecPtr &codec,      // Protobuf协议编解码器
               const muduo::net::TcpConnectionPtr &conn,  // 底层TCP连接
               const threadpool::ptr &pool);       // 工作线程池
    
    // 打开信道:处理客户端打开信道的请求
    void openChannel(const openChannelRequestPtr &req);
    
    // 关闭信道:处理客户端关闭信道的请求
    void closeChannel(const closeChannelRequestPtr &req);
    
    // 获取信道:根据信道ID查找对应的信道对象
    Channel::ptr getChannel(const std::string &cid);
    
private: 
    // 基础响应函数:构造并发送标准的响应消息
    void basicResponse(bool ok, const std::string &rid, const std::string &cid);
    
private: 
    muduo::net::TcpConnectionPtr _conn;   // 底层TCP连接对象
    ProtobufCodecPtr _codec;              // Protobuf协议编解码器
    ConsumerManager::ptr _cmp;            // 消费者管理器,用于消息路由
    VirtualHost::ptr _host;               // 虚拟机主机环境
    threadpool::ptr _pool;                // 异步工作线程池
    ChannelManager::ptr _channels;        // 信道管理器,管理本连接的所有信道
}; 

这个类还是很简单就能实现的

cpp 复制代码
// Connection类:管理单个TCP连接,提供信道的创建、关闭和查询功能
class Connection { 
public: 
    using ptr = std::shared_ptr<Connection>;  // 智能指针别名,便于资源管理
    
    // 构造函数:初始化连接所需的各个组件
    Connection(const VirtualHost::ptr &host,       // 虚拟机主机环境
               const ConsumerManager::ptr &cmp,    // 消费者管理器
               const ProtobufCodecPtr &codec,      // Protobuf协议编解码器
               const muduo::net::TcpConnectionPtr &conn,  // 底层TCP连接
               const ThreadPool::ptr &pool)        // 工作线程池
        : _conn(conn), _codec(codec), _cmp(cmp), 
          _host(host), _pool(pool), 
          _channels(std::make_shared<ChannelManager>()) {}  // 创建信道管理器
    
    // 打开信道:处理客户端打开信道的请求
    void openChannel(const openChannelRequestPtr &req) { 
        // 1. 尝试创建信道,检查信道ID是否重复
        bool ret = _channels->openChannel(req->cid(), _host, _cmp, _codec, _conn, _pool);
        if (ret == false) { 
            // 创建失败,记录日志并返回错误响应
            DLOG("创建信道的时候,信道ID重复了"); 
            return basicResponse(false, req->rid(), req->cid()); 
        } 
        
        // 2. 创建成功,记录日志
        DLOG("%s 信道创建成功!", req->cid().c_str()); 
        
        // 3. 返回成功响应给客户端
        return basicResponse(true, req->rid(), req->cid()); 
    } 
    
    // 关闭信道:处理客户端关闭信道的请求
    void closeChannel(const closeChannelRequestPtr &req) { 
        // 关闭指定信道
        _channels->closeChannel(req->cid()); 
        // 返回成功响应给客户端
        return basicResponse(true, req->rid(), req->cid()); 
    } 
    
    // 获取信道:根据信道ID查找对应的信道对象
    Channel::ptr getChannel(const std::string &cid) { 
        return _channels->getChannel(cid); 
    } 
    
private: 
    // 基础响应函数:构造并发送标准的响应消息
    void basicResponse(bool ok, const std::string &rid, const std::string &cid) { 
        basicCommonResponse resp;        // 创建响应消息对象
        resp.set_rid(rid);              // 设置请求ID
        resp.set_cid(cid);              // 设置信道ID
        resp.set_ok(ok);                // 设置操作结果(成功/失败)
        _codec->send(_conn, resp);      // 通过编解码器发送响应
    } 
    
private: 
    muduo::net::TcpConnectionPtr _conn;   // 底层TCP连接对象
    ProtobufCodecPtr _codec;              // Protobuf协议编解码器
    ConsumerManager::ptr _cmp;            // 消费者管理器,用于消息路由
    VirtualHost::ptr _host;               // 虚拟机主机环境
    ThreadPool::ptr _pool;                // 异步工作线程池
    ChannelManager::ptr _channels;        // 信道管理器,管理本连接的所有信道
}; 

二 ConnectionManager类 - 连接集中管理

职责:

作为连接管理的单例或全局管理器,维护所有活跃连接的注册表,确保连接资源的正确分配与回收。

核心机制:

  • 线程安全容器:使用互斥锁保护的哈希表存储连接映射
  • 连接标识:以Muduo的TcpConnectionPtr作为连接的唯一键值
  • 自动清理:连接断开时自动从管理器中移除

关键接口:

newConnection():注册新建立的连接

  1. 检查连接是否已存在(防止重复注册)
  2. 创建Connection对象并建立完整资源链
  3. 将连接加入全局管理映射表

delConnection():移除已断开的连接

  • 从管理映射表中擦除连接记录
  • 触发连接对象的析构与资源释放
  • 连接检索功能

getConnection():根据底层连接句柄查找对应的Connection对象

  • 线程安全的查找操作
  • 返回智能指针,支持空值表示连接不存在

这个类还是很简单的,所以我们直接就写出来了

cpp 复制代码
// ConnectionManager类:全局连接管理器,负责所有连接的生命周期管理
class ConnectionManager { 
public: 
    using ptr = std::shared_ptr<ConnectionManager>;  // 智能指针别名
    
    ConnectionManager() {}  // 默认构造函数
    
    // 创建新连接:当新的TCP连接建立时调用此函数
    void newConnection(const VirtualHost::ptr &host,       // 虚拟机主机环境
                       const ConsumerManager::ptr &cmp,    // 消费者管理器
                       const ProtobufCodecPtr &codec,      // Protobuf协议编解码器
                       const muduo::net::TcpConnectionPtr &conn,  // 底层TCP连接
                       const ThreadPool::ptr &pool)// 工作线程池 
    {
        std::unique_lock<std::mutex> lock(_mutex);  // 加锁,保证线程安全
        
        // 检查连接是否已存在(防止重复添加)
        auto it = _conns.find(conn);
        if (it != _conns.end()) 
        { 
            return ;  // 连接已存在,直接返回
        } 
        
        // 创建新的Connection对象
        Connection::ptr self_conn = std::make_shared<Connection>(host, cmp, codec, conn, pool);
        
        // 将新连接添加到连接映射表中
        _conns.insert(std::make_pair(conn, self_conn));
    } 
    
    // 删除连接:当TCP连接断开时调用此函数
    void delConnection(const muduo::net::TcpConnectionPtr &conn) { 
        std::unique_lock<std::mutex> lock(_mutex);  // 加锁,保证线程安全
        _conns.erase(conn);  // 从连接映射表中删除指定连接
    } 
    
    // 获取连接:根据底层TCP连接对象查找对应的Connection对象
    Connection::ptr getConnection(const muduo::net::TcpConnectionPtr &conn) { 
        std::unique_lock<std::mutex> lock(_mutex);  // 加锁,保证线程安全
        
        auto it = _conns.find(conn);  // 查找连接
        if (it == _conns.end()) { 
            return Connection::ptr();  // 连接不存在,返回空指针
        } 
        
        return it->second;  // 返回找到的连接对象
    } 
    
private: 
    std::mutex _mutex;  // 互斥锁,保护连接映射表的线程安全访问
    
    // 连接映射表:key为底层TCP连接对象,value为对应的Connection对象
    std::unordered_map<muduo::net::TcpConnectionPtr, Connection::ptr> _conns;
}; 

三. 工作流程详解

3.1 连接建立流程

  • 客户端建立TCP连接,Muduo网络库创建TcpConnection
  • ConnectionManager收到新连接通知,调用newConnection()
  • 管理器创建Connection对象,传入所有必要的依赖组件
  • 连接被注册到全局映射表,完成初始化

3.2 信道创建流程

  • 客户端发送openChannelRequest请求
  • Connection的openChannel()方法被调用
  • 信道管理器检查请求中的信道ID是否重复
  • 若ID可用,创建新信道并配置完整的处理链
  • 生成响应消息,通过协议编解码器发送回客户端

3.3 连接关闭流程

  • 检测到TCP连接断开或收到关闭请求
  • ConnectionManager调用delConnection()移除连接
  • 连接对象的所有信道被自动清理
  • 关联的虚拟机资源、消费者等组件被安全释放

四.代码总结

注意我们的代码都是存放在下面这个connection.hpp里面的

cpp 复制代码
#include "channel.hpp"

namespace mymq
{

    // Connection类:管理单个TCP连接,提供信道的创建、关闭和查询功能
    class Connection
    {
    public:
        using ptr = std::shared_ptr<Connection>; // 智能指针别名,便于资源管理

        // 构造函数:初始化连接所需的各个组件
        Connection(const VirtualHost::ptr &host,             // 虚拟机主机环境
                   const ConsumerManager::ptr &cmp,          // 消费者管理器
                   const ProtobufCodecPtr &codec,            // Protobuf协议编解码器
                   const muduo::net::TcpConnectionPtr &conn, // 底层TCP连接
                   const ThreadPool::ptr &pool)              // 工作线程池
            : _conn(conn), _codec(codec), _cmp(cmp),
              _host(host), _pool(pool),
              _channels(std::make_shared<ChannelManager>())
        {
        } // 创建信道管理器

        // 打开信道:处理客户端打开信道的请求
        void openChannel(const openChannelRequestPtr &req)
        {
            // 1. 尝试创建信道,检查信道ID是否重复
            bool ret = _channels->openChannel(req->cid(), _host, _cmp, _codec, _conn, _pool); // 直接创建信道
            if (ret == false)
            {
                // 创建失败,记录日志并返回错误响应
                DLOG("创建信道的时候,信道ID重复了");
                return basicResponse(false, req->rid(), req->cid());
            }

            // 2. 创建成功,记录日志
            DLOG("%s 信道创建成功!", req->cid().c_str());

            // 3. 返回成功响应给客户端
            return basicResponse(true, req->rid(), req->cid());
        }

        // 关闭信道:处理客户端关闭信道的请求
        void closeChannel(const closeChannelRequestPtr &req)
        {
            // 关闭指定信道
            _channels->closeChannel(req->cid());
            // 返回成功响应给客户端
            return basicResponse(true, req->rid(), req->cid());
        }

        // 获取信道:根据信道ID查找对应的信道对象
        Channel::ptr getChannel(const std::string &cid)
        {
            return _channels->getChannel(cid);
        }

    private:
        // 基础响应函数:构造并发送标准的响应消息
        void basicResponse(bool ok, const std::string &rid, const std::string &cid)
        {
            basicCommonResponse resp;  // 创建响应消息对象
            resp.set_rid(rid);         // 设置请求ID
            resp.set_cid(cid);         // 设置信道ID
            resp.set_ok(ok);           // 设置操作结果(成功/失败)
            _codec->send(_conn, resp); // 通过编解码器发送响应
        }

    private:
        muduo::net::TcpConnectionPtr _conn; // 底层TCP连接对象
        ProtobufCodecPtr _codec;            // Protobuf协议编解码器
        ConsumerManager::ptr _cmp;          // 消费者管理器,用于消息路由
        VirtualHost::ptr _host;             // 虚拟机主机环境
        ThreadPool::ptr _pool;              // 异步工作线程池
        ChannelManager::ptr _channels;      // 信道管理器,管理本连接的所有信道
    };

    // ConnectionManager类:全局连接管理器,负责所有连接的生命周期管理
    class ConnectionManager
    {
    public:
        using ptr = std::shared_ptr<ConnectionManager>; // 智能指针别名

        ConnectionManager() {} // 默认构造函数

        // 创建新连接:当新的TCP连接建立时调用此函数
        void newConnection(const VirtualHost::ptr &host,             // 虚拟机主机环境
                           const ConsumerManager::ptr &cmp,          // 消费者管理器
                           const ProtobufCodecPtr &codec,            // Protobuf协议编解码器
                           const muduo::net::TcpConnectionPtr &conn, // 底层TCP连接
                           const ThreadPool::ptr &pool)              // 工作线程池
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁,保证线程安全

            // 检查连接是否已存在(防止重复添加)
            auto it = _conns.find(conn);
            if (it != _conns.end())
            {
                return; // 连接已存在,直接返回
            }

            // 创建新的Connection对象
            Connection::ptr self_conn = std::make_shared<Connection>(host, cmp, codec, conn, pool);

            // 将新连接添加到连接映射表中
            _conns.insert(std::make_pair(conn, self_conn));
        }

        // 删除连接:当TCP连接断开时调用此函数
        void delConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁,保证线程安全
            _conns.erase(conn);                        // 从连接映射表中删除指定连接
        }

        // 获取连接:根据底层TCP连接对象查找对应的Connection对象
        Connection::ptr getConnection(const muduo::net::TcpConnectionPtr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex); // 加锁,保证线程安全

            auto it = _conns.find(conn); // 查找连接
            if (it == _conns.end())
            {
                return Connection::ptr(); // 连接不存在,返回空指针
            }

            return it->second; // 返回找到的连接对象
        }

    private:
        std::mutex _mutex; // 互斥锁,保护连接映射表的线程安全访问

        // 连接映射表:key为底层TCP连接对象,value为对应的Connection对象
        std::unordered_map<muduo::net::TcpConnectionPtr, Connection::ptr> _conns;
    };

} 

五.代码测试

我们所有的测试都是在下面这个test.cpp里面的

cpp 复制代码
#include "../..//mqserver/connection.hpp" 

int main()
{
    // 1. 创建连接管理器实例
    // 使用智能指针管理ConnectionManager生命周期
    mymq::ConnectionManager::ptr cmp = std::make_shared<mymq::ConnectionManager>();
    
    // 2. 创建新连接
    // 向连接管理器注册一个新的网络连接
    cmp->newConnection(
        // 虚拟机主机环境参数
        std::make_shared<mymq::VirtualHost>(
            "host1",                         // 主机名称
            "./data/host1/message/",         // 消息存储目录
            "./data/host1/host1.db"          // 主机数据库文件路径
        ),
        
        // 消费者管理器参数
        std::make_shared<mymq::ConsumerManager>(),
        
        // Protobuf协议编解码器参数(此处使用默认构造)
        mymq::ProtobufCodecPtr(),
        
        // 底层TCP连接对象(此处使用空指针,实际使用时应传入有效的TcpConnectionPtr)
        muduo::net::TcpConnectionPtr(),
        
        // 工作线程池参数(此处使用空指针,实际使用时应传入有效的线程池实例)
        ThreadPool::ptr()
    );
    
    return 0;  // 程序正常退出
}

makefile

cpp 复制代码
test:test.cpp ../../third/include/muduo/protobuf/codec.cc ../../mqcommon/msg.pb.cc ../../mqcommon/proto.pb.cc
	g++ $^ -o $@  -I ../../third/include -L ../../third/lib -lmuduo_net -lmuduo_base -lpthread -lprotobuf -lz -lsqlite3
相关推荐
Leinwin2 小时前
OpenClaw 多 Agent 协作框架的并发限制与企业化规避方案痛点直击
java·运维·数据库
2401_865382502 小时前
信息化项目运维与运营的区别
运维·运营·信息化项目·政务信息化
漠北的哈士奇2 小时前
VMware Workstation导入ova文件时出现闪退但是没有报错信息
运维·vmware·虚拟机·闪退·ova
如意.7592 小时前
【Linux开发工具实战】Git、GDB与CGDB从入门到精通
linux·运维·git
运维小欣3 小时前
智能体选型实战指南
运维·人工智能
yy55273 小时前
Nginx 性能优化与监控
运维·nginx·性能优化
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ4 小时前
Linux 查询某进程文件所在路径 命令
linux·运维·服务器
05大叔5 小时前
网络基础知识 域名,JSON格式,AI基础
运维·服务器·网络
安当加密5 小时前
无需改 PAM!轻量级 RADIUS + ASP身份认证系统 实现 Linux 登录双因子认证
linux·运维·服务器
dashizhi20155 小时前
服务器共享禁止保存到本地磁盘、共享文件禁止另存为本地磁盘、移动硬盘等
运维·网络·stm32·安全·电脑