全部版块 我的主页
论坛 经济学论坛 三区 环境经济学
110 0
2025-12-02

一. 项目概述

在前期学习过程中,我们接触过阻塞队列(BlockingQueue),并了解到其核心用途之一是实现“生产者-消费者模型”。该模型广泛应用于后端系统开发中,具有诸多优势:

  • 促进模块间的解耦
  • 支持并发执行,提升处理效率
  • 有效应对任务负载波动
  • 具备削峰填谷能力,优化资源利用率

在实际的分布式架构中,不同服务器之间常需通过生产者-消费者机制传递任务。为此,通常会将基础的队列功能封装为独立服务,并扩展更多特性。这种可独立部署的服务即为业界所称的“消息队列”(Message Queue, MQ)。

当前已有多种成熟的消息队列实现方案,例如:

  • RabbitMQ
  • Kafka
  • RocketMQ
  • ActiveMQ

其中,RabbitMQ 因其功能完善、生态丰富且广泛应用而备受青睐。接下来的内容中,我们将借鉴 RabbitMQ 的设计思路,动手实现一个简易版本的消息队列系统。

技术选型与开发环境

操作系统:Linux(支持 Centos-7.6 或 Ubuntu-22.04)
编辑工具:VSCode / Vim
编译调试:g++ / gdb
构建管理:Makefile

核心技术栈

编程语言:C++
选择 C++ 主要出于对高性能和底层资源精确控制的需求。对于需要高吞吐、低延迟的中间件系统而言,C++ 能够提供更强的运行效率和系统级操作能力。

序列化方式:Protobuf(Protocol Buffers)
采用 Protobuf 实现数据的二进制序列化。它具备跨平台、体积小、解析快等优点,非常适合网络传输场景,同时便于多语言服务之间的数据交互。

通信架构:自定义应用层协议 + Muduo 网络库
为了避免从零实现 Socket 编程带来的复杂性(如粘包/拆包、连接维护等问题),我们选用 Muduo 作为底层网络框架。Muduo 是一个基于 Reactor 模式的高质量 C++ TCP 库,内部使用 epoll 事件驱动机制,能够轻松支撑高并发连接,使开发者更专注于业务逻辑而非网络细节。

持久化存储:SQLite3
为防止因服务重启导致消息丢失,需将关键数据落盘保存。SQLite3 是一款轻量级嵌入式数据库,无需独立进程即可运行,支持 ACID 事务,满足本项目对简单可靠的数据持久化需求。

测试保障:GTest(Google Test)
为确保代码质量与稳定性,引入 GTest 单元测试框架。通过对各核心组件编写详尽的测试用例,验证功能正确性,增强系统的可维护性和迭代安全性。

二. 环境搭建

2.1 基础工具配置

本项目基于 Ubuntu 24.04 LTS 进行开发。

首先需要安装一系列基础组件以支撑后续开发流程。

sudo apt-get update && sudo apt-get install -y \
    wget \
    lrzsz \
    gcc g++ \
    make \
    gdb \
    git \
    cmake

安装完成后,可通过以下命令一键检查是否所有必要组件均已成功部署。

echo "=== 检查工具安装情况 ===" && \
for tool in wget lrzsz gcc g++ make gdb git cmake; do
    if command -v $tool &> /dev/null; then
        echo "? $tool 已安装: $($tool --version 2>/dev/null | head -n1)"
    else
        echo "? $tool 未安装"
    fi
done

2.2 Protobuf 安装流程

2.2.1 安装依赖项

在开始编译 ProtoBuf(Protocol Buffers)前,必须确保系统已安装必要的构建工具和库文件,包括 autoconf、automake、libtool、curl、make、g++ 和 unzip。这些是完成源码编译的基础环境,任一缺失都可能导致构建失败。

Ubuntu / Debian 用户请执行以下命令进行安装:

sudo apt-get update
sudo apt-get install autoconf automake libtool curl make g++ unzip -y

安装完毕后,建议再次确认所有依赖项状态正常,随后即可进入源码下载阶段。若遇问题,可查阅 ProtoBuf 官方文档或对应发行版的包管理指南获取帮助。

2.2.2 获取源码包

访问 ProtoBuf 的官方发布页面:

Releases · protocolbuffers/protobuf

该地址与前述链接一致。

推荐下载最新稳定版本,例如 v21.11,具体版本可根据本地环境灵活选择。

进入发布页后可见如下内容:

若仅用于 C++ 开发,可选择 cpp.zip;
若用于 Java,则下载 java.zip;
其他语言按需选取对应压缩包。
如需支持全部语言,建议直接下载 all.zip。

本项目选择全语言版本。

点击下载按钮获取文件。

接着登录目标服务器,执行 rz 命令上传文件。

上传完成后进行解压操作。

unzip protobuf-all-21.11.zip

解压结果如下:

此时得到的目录即为 Protobuf 的完整源码,下一步将对其进行编译。

2.2.3 编译构建过程

进入解压后的源码根目录,依次执行以下步骤。

第一步:运行 autogen.sh 脚本

此脚本用于生成 configure 配置文件,为后续的 configure 步骤做准备。

./autogen.sh

2.2.3.2 第二步:运行 configure

在配置过程中,提供两种不同的安装方式,用户可根据实际需求选择其一:

默认安装模式
若采用默认设置,protobuf 将被安装至系统预设路径:

/usr/local

此时,相关的库文件、可执行程序等资源将自动分布于该目录下的各个子目录中。

./configure

自定义安装路径
为便于管理与维护,推荐将所有组件统一部署到指定目录。例如,设定安装位置为:

/usr/local/protobuf

所有生成的文件都将集中存放于此。

./configure --prefix=/usr/local/protobuf

出于结构统一考虑,本文后续操作均基于自定义安装路径方式进行。

完成配置后,当前工作目录下会生成相应构建文件:

这表明环境已准备就绪,可以进入下一步编译流程,直接执行 make 命令。

2.2.3.3 第三步:执行编译

在完成 configure 配置之后,启动编译过程,请运行以下指令:

make            # 编译源码

建议在执行

make check

时保持耐心,此阶段会自动运行多项测试用例,以确保整个编译流程正确无误。

我们首先执行:

等待约15分钟……

2.2.3.4 第四步:验证编译结果

为确认编译是否成功,需执行如下命令进行检查:

make check      # 验证编译结果(可选,约需15分钟)

具体操作为运行:

继续等待约15分钟。

在整个执行过程中,可能会出现大量警告信息,但只要未出现红色错误提示,则视为正常现象。

若遇到如下报错情况:

其原因在于 test 模块包含大量测试案例,这些案例对服务器运行环境要求较高,尤其是内存和交换空间(swap)资源。解决方法是增加 swap 分区大小,具体步骤如下:

步骤一:查看当前 SWAP 状态
操作前,先通过命令检查 Ubuntu 系统当前的 SWAP 使用情况:

sudo swapon --show

该命令将列出所有已激活的 SWAP 区域。若无任何输出,则表示系统尚未配置 SWAP。

步骤二:创建 SWAP 文件
分配一个 1GB 大小的 swap 文件:

sudo fallocate -l 1G /swapfile

如果在执行过程中提示 fallocate failed: Text file busy,说明当前文件或资源正被占用。

此时应采取以下措施:

  • 关闭所有正在使用的 SWAP 分区:
sudo swapoff -a
  • 重新尝试创建 SWAP 文件:
sudo fallocate -l 1G /swapfile

步骤三:设置 SWAP 文件权限
为保障系统安全,需将 SWAP 文件权限限制为仅 root 用户可读写:

sudo chmod 600 /swapfile

步骤四:初始化 SWAP 区域
使用 mkswap 工具在目标文件上建立 Linux 可识别的 SWAP 区域:

sudo mkswap /swapfile

步骤五:启用 SWAP 文件
通过以下命令激活新创建的 swap 文件:

sudo swapon /swapfile

验证 SWAP 是否生效
再次运行以下命令确认 SWAP 已成功启用:

sudo swapon --show

或者使用替代命令:

free -h

步骤六:实现永久化配置
为防止重启后配置丢失,在修改系统关键文件前建议先进行备份:

  • 备份原始 fstab 文件:
sudo cp /etc/fstab /etc/fstab.bak
  • 将 SWAP 信息写入 /etc/fstab,确保开机自动挂载:
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

(建议先扩容至 3GB,再执行 make check。若仍失败,进一步扩展至 5GB 并重新运行测试。)

我们现在尝试将 swap 扩展至 3GB:

可以看到当前系统已存在一个约 1.9GB 的 swap 文件。

接下来我们新建一个 3GB 的 swap 文件:

# 创建额外的3G swap文件(与现有swap共存)
sudo fallocate -l 3G /swapfile2
sudo chmod 600 /swapfile2
sudo mkswap /swapfile2
sudo swapon /swapfile2

# 验证总swap大小(现在应该有约4.9G)
free -h
sudo swapon --show

完成后,重新执行 make check 进行验证:

cd /root/protobuf/protobuf-21.11
make check

……等待中

结果显示仍然报错,说明 3GB 不足以满足测试需求。现在我们将 swap 提升至 5GB 再次尝试:

# 1. 禁用当前的额外swap
sudo swapoff /swapfile2

# 2. 删除3G文件,创建5G文件
sudo rm -f /swapfile2
sudo fallocate -l 5G /swapfile2
sudo chmod 600 /swapfile2
sudo mkswap /swapfile2
sudo swapon /swapfile2

# 3. 验证新的swap配置
free -h
sudo swapon --show

然后再次运行 make check:

# 再次执行make check
cd /root/protobuf/protobuf-21.11
make check

等待……

最终显示成功通过。注意:本次实验无需将 swap 配置设为永久生效。

2.2.3.5 第五步:安装至系统目录

当 make check 成功完成后,即可将编译成果正式安装到系统目录中:

sudo make install  # 安装到系统目录

该过程执行速度较快。

2.2.3.6 第六步:更新系统环境配置

请回顾此前的操作:

在第二步执行 configure 时,若当时使用的是默认方式(即 ./configure),则 protobuf 已可直接使用,无需额外配置。

但如果选择了自定义安装路径,则需要手动将相关路径添加至系统环境变量中。编辑 /etc/profile 文件:

sudo vim /etc/profile

在文件末尾加入以下内容:

# 动态库搜索路径(运行时)
# 指定程序在加载运行期间查找动态链接库的路径,除了系统默认路径外
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/protobuf/lib/

# 静态库搜索路径(编译时)
# 指定程序在编译期间查找静态库的路径
export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/protobuf/lib/

# 可执行程序搜索路径
# 指定系统在哪些目录中查找可执行文件
export PATH=$PATH:/usr/local/protobuf/bin/

# C 程序头文件搜索路径
# 指定 C 编译器查找头文件(.h 文件)的目录
export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/local/protobuf/include/

# C++ 程序头文件搜索路径  
# 指定 C++ 编译器查找头文件(.h/.hpp 文件)的目录
export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/local/protobuf/include/

# pkg-config 工具搜索路径
# 指定 pkg-config 查找 .pc 配置文件的目录,用于获取编译和链接参数
export PKG_CONFIG_PATH=/usr/local/protobuf/lib/pkgconfig/

保存并退出编辑器。

最后一步,刷新 profile 配置使其立即生效:

source /etc/profile

2.2.3.7 第七步:确认安装成功

执行以下命令进行最终验证:

protoc --version

如能正常显示版本信息,则表明 protobuf 安装成功。

2.3 安装 Muduo 库

Muduo 库的官方网站为:

在开始安装 Muduo 库之前,首先需要确保系统中已安装必要的依赖工具。

sudo apt-get install libz-dev libboost-all-dev

接着,前往项目的官方仓库获取源码:

GitHub - chenshuo/muduo: Event-driven network library for multi-threaded Linux server in C++11

使用 rz 命令将下载的源码文件上传至远程服务器。

unzip muduo-master.zip
cd muduo-master

完成上传后,进入编译与安装流程。

./build.sh

该步骤对应的是源码的编译过程。

./build.sh install

随后执行的命令则用于安装编译生成的内容。那么这些文件究竟被安装到了哪个路径?实际上,默认情况下,所有产物会被放置在上一级目录中的 build 文件夹内。

我们所需的核心库文件均位于此目录下!

值得注意的是,该目录中还包含大量官方提供的使用示例,以下列出的均为已编译完成的可执行程序。

我们可以选取其中一个进行功能测试。

同时打开另一个终端窗口,用于发起连接或发送测试数据。

此时观察原终端的输出状态,其显示内容已发生变化。

这表明服务端已正常运行并成功接收客户端请求——安装配置成功!

从结果可见,每发送一个字符,服务器都能准确回显,通信无误。

2.4 安装 sqlite3 与 GTest

sudo apt-get install sqlite3 libsqlite3-dev

接下来继续安装辅助开发与测试所需的组件:sqlite3 和 Google Test(GTest)框架。

sudo apt-get install libgtest-dev

安装完成后,编写一个简单的测试文件以验证环境是否配置正确。

// 引入 Google Test 框架的头文件
#include <gtest/gtest.h>

// 定义一个简单的加法函数
int add(int a, int b) {
    return a + b;
}

// 创建测试用例
// TEST 是 Google Test 的宏,用于定义测试
// 参数1: testCase - 测试用例的名称
// 参数2: test1 - 测试的名称
TEST(testCase, test1) {
    // EXPECT_EQ 是断言宏,检查两个值是否相等
    // 这里测试 add(2,3) 的结果是否等于 5
    EXPECT_EQ(add(2, 3), 5);
}

// 程序主函数
int main(int argc, char **argv) {
    // 初始化 Google Test 框架
    // 这行代码会解析命令行参数(如 --gtest_filter 等)
    testing::InitGoogleTest(&argc, argv);
    
    // 运行所有测试用例并返回结果
    // RUN_ALL_TESTS() 会执行所有 TEST 定义的测试
    // 返回 0 表示所有测试通过,非 0 表示有测试失败
    return RUN_ALL_TESTS();
}

尝试对该测试文件进行编译。

# 需要链接 gtest 库
g++ main.cpp -lgtest

编译通过且运行正常,说明相关组件已成功安装并可用。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群