百万并发压测
测试环境
- 云服务器环境
- 2核2G 2M Linux华为云服务器
- Ubuntu系统
- 本地电脑环境
- 处理器:AMD Ryzen 7 4800H with Radeon Graphics2.90 GHz
- 已安装的内存(RAM):16.0GB(15.4GB可用)
- 系统类型:64位操作系统,基于x64的处理器
测试结果
- 响应:耗时1.20599秒,高负载情况下实现百万并发
- 吞吐量:每秒处理829365日志,处理数据量79M,实现高并发情况下的数据处理性能
- 多线程并发:5个线程并行处理日志,充分利用CPU提高运行性能
当前日志器:root 未检测到日志格式,默认设置为[ %d{%H:%M:%S}%T%t%T[%p]%T[%c]%T%f:%l%T%m%n ]!
当前日志器:root 未检测到落地方向,默认设置为标准输出!
DEBUG 同步日志器: root创建成功...
[09:02:59][140191453075264][INFO][root][logger.cc:31] ************************************************
[09:02:59][140191453075264][INFO][root][logger.cc:32] 异步日志测试: 1 线程, 1000000 条日志
DEBUG异步日志器: async_bench_logger1创建成功...
线程数量: 1
日志总数量: 1000000
单条日志大小: 100 字节
总耗时: 1.31725 秒
每秒日志数量: 759204 条
每秒日志数据量: 72 MB
[09:03:01][140191453075264][INFO][root][logger.cc:44] ************************************************
[09:03:01][140191453075264][INFO][root][logger.cc:31] ************************************************
[09:03:01][140191453075264][INFO][root][logger.cc:32] 异步日志测试: 5 线程, 1000000 条日志
DEBUG异步日志器: async_bench_logger2创建成功...
线程数量: 5
日志总数量: 1000000
单条日志大小: 100 字节
总耗时: 0.860284 秒
每秒日志数量: 1170953 条
每秒日志数据量: 111 MB
[09:03:01][140191453075264][INFO][root][logger.cc:44] ************************************************
[09:03:01][140191453075264][INFO][root][logger.cc:10] ************************************************
[09:03:01][140191453075264][INFO][root][logger.cc:11] 同步日志测试: 1 线程, 1000000 条日志
DEBUG 同步日志器: sync_bench_logger1创建成功...
线程数量: 1
日志总数量: 1000000
单条日志大小: 100 字节
总耗时: 1.1581 秒
每秒日志数量: 863533 条
每秒日志数据量: 82 MB
[09:03:03][140191453075264][INFO][root][logger.cc:23] ************************************************
[09:03:03][140191453075264][INFO][root][logger.cc:10] ************************************************
[09:03:03][140191453075264][INFO][root][logger.cc:11] 同步日志测试: 5 线程, 1000000 条日志
DEBUG 同步日志器: sync_bench_logger2创建成功...
线程数量: 5
日志总数量: 1000000
单条日志大小: 100 字节
总耗时: 1.10798 秒
每秒日志数量: 902719 条
每秒日志数据量: 86 MB
[09:03:04][140191453075264][INFO][root][logger.cc:23] ************************************************
root@hcss-ecs-b4a9:/home/bitlog/bench# make
g++ -g -std=c++11 logger.cc -o logger -lpthread
root@hcss-ecs-b4a9:/home/bitlog/bench# ./logger
当前日志器:root 未检测到日志格式,默认设置为[ %d{%H:%M:%S}%T%t%T[%p]%T[%c]%T%f:%l%T%m%n ]!
当前日志器:root 未检测到落地方向,默认设置为标准输出!
DEBUG 同步日志器: root创建成功...
[09:04:32][140250054625088][INFO][root][logger.cc:10] ************************************************
[09:04:32][140250054625088][INFO][root][logger.cc:11] async日志测试: 1 线程, 1000000 条日志
DEBUG异步日志器: async_bench_logger1创建成功...
线程数量: 1
日志总数量: 1000000
单条日志大小: 100 字节
总耗时: 1.53762 秒
每秒日志数量: 650421 条
每秒日志数据量: 62 MB
[09:04:34][140250054625088][INFO][root][logger.cc:23] ************************************************
[09:04:34][140250054625088][INFO][root][logger.cc:10] ************************************************
[09:04:34][140250054625088][INFO][root][logger.cc:11] async日志测试: 5 线程, 1000000 条日志
DEBUG异步日志器: async_bench_logger2创建成功...
线程数量: 5
日志总数量: 1000000
单条日志大小: 100 字节
总耗时: 0.923734 秒
每秒日志数量: 1087104 条
每秒日志数据量: 103 MB
[09:04:35][140250054625088][INFO][root][logger.cc:23] ************************************************
[09:04:35][140250054625088][INFO][root][logger.cc:10] ************************************************
[09:04:35][140250054625088][INFO][root][logger.cc:11] sync日志测试: 1 线程, 1000000 条日志
DEBUG 同步日志器: sync_bench_logger3创建成功...
线程数量: 1
日志总数量: 1000000
单条日志大小: 100 字节
总耗时: 1.37098 秒
每秒日志数量: 729480 条
每秒日志数据量: 69 MB
[09:04:36][140250054625088][INFO][root][logger.cc:23] ************************************************
[09:04:36][140250054625088][INFO][root][logger.cc:10] ************************************************
[09:04:36][140250054625088][INFO][root][logger.cc:11] sync日志测试: 5 线程, 1000000 条日志
DEBUG 同步日志器: sync_bench_logger4创建成功...
线程数量: 5
日志总数量: 1000000
单条日志大小: 100 字节
总耗时: 1.20599 秒
每秒日志数量: 829365 条
每秒日志数据量: 79 MB
[09:04:37][140250054625088][INFO][root][logger.cc:23] ************************************************
容错测试
磁盘故障注入测试
- 磁盘写满测试:通过不断的向磁盘中写入数据,直到磁盘满载,从而测试系统在无法写入日志文件如何运行,期望系统可以正确捕获异常,并正确处理日志文件的写入失败
- 磁盘只读测试:日志文件目录挂载为只读,目的就是在无法写入日志的时候,是否可以识别出该情况【测试失败,后期更改】
#include "../logs/maglog.h"
#include <fstream>
#include <iostream>
void testDiskFull() {
LOGI("开始磁盘写满测试");
// 模拟磁盘写满
std::ofstream ofs("/home/bitlog/test/fill_disk.txt", std::ios::binary);
const size_t bufferSize = 1024 * 1024; // 1 MB
char buffer[bufferSize] = {0};
try {
while (true) {
ofs.write(buffer, bufferSize);
if (ofs.fail()) {
LOGE("磁盘已满或写入失败!");
break;
}
}
} catch (const std::exception &e) {
LOGE("磁盘写满测试异常: %s", e.what());
}
LOGI("磁盘写满测试结束");
}
void testDiskReadOnly() {
LOGI("开始磁盘只读测试");
// 将目录挂载为只读
std::string command = "sudo mount -o remount,ro /home/bitlog/log";
if (system(command.c_str()) != 0) {
LOGE("无法将磁盘目录挂载为只读");
}
LOGI("磁盘只读测试结束");
}
int main() {
// 执行磁盘写满测试
testDiskFull();
// 执行磁盘只读测试
testDiskReadOnly();
return 0;
}
网络故障测试
- 网络延迟测试:模拟日志系统在网络波动时候的行为,经测试可以实现在高延迟网络条件下继续进行稳定的传输数据
#include"../logs/maglog.h"
#include <cstdlib>
#include <iostream>
void testNetworkDelay()
{
LOGI("开始网络延迟测试");
// 删除现有的 netem 规则,防止冲突
std::string deleteCommand = "sudo tc qdisc del dev eth0 root";
int deleteResult = system(deleteCommand.c_str());
if (deleteResult == 0) {
LOGI("成功删除现有的网络延迟规则");
} else {
LOGW("未找到现有的网络延迟规则,可能未设置或已被删除");
}
// 添加新的网络延迟规则
std::string command = "sudo tc qdisc add dev eth0 root netem delay 100ms";
int addResult = system(command.c_str());
if (addResult == 0) {
LOGI("成功引入100ms的网络延迟");
} else {
LOGE("无法引入网络延迟,命令执行失败");
}
// 打印当前的网络配置
std::string showCommand = "sudo tc qdisc show dev eth0";
LOGI("当前网络配置如下:");
int showResult = system(showCommand.c_str());
if (showResult != 0) {
LOGE("无法显示当前的网络配置");
}
LOGI("网络延迟测试结束");
}
int main(){
// 执行网络延迟测试
testNetworkDelay();
return 0;
}
资源限制测试
- CPU压力测试:通过引入CPU高负载,测试系统在高CPU占用情况下的性能。希望看到系统是否能够继续高效地处理日志记录任务
- 内存压力测试:通过模拟高内存占用,测试系统在内存资源有限时的表现。希望确认系统在内存压力下的稳定性和响应能力
#include "../logs/maglog.h"
#include <cstdlib>
void testCpuStress() {
LOGI("开始CPU压力测试");
// 模拟CPU高负载
std::string command = "stress-ng --cpu 2 --timeout 60s";
if (system(command.c_str()) != 0) {
LOGE("CPU压力测试失败");
}
LOGI("CPU压力测试结束");
}
void testMemoryStress() {
LOGI("开始内存压力测试");
// 模拟内存压力
std::string command = "stress-ng --vm 1 --vm-bytes 90% --timeout 60s";
if (system(command.c_str()) != 0) {
LOGE("内存压力测试失败");
}
LOGI("内存压力测试结束");
}
int main() {
// 执行CPU压力测试
testCpuStress();
// 执行内存压力测试
testMemoryStress();
return 0;
}
混合读写测试
实时读取写入测试,模拟高并发场景下的并发读写日志,测试日志的性能和稳定性
#include"../logs/maglog.h"
#include <fstream>
#include <thread>
#include <vector>
#include <mutex>
#include <chrono>
#include <string>
void writeLogs(int numMessages, int threadId) {
for (int i = 0; i < numMessages; ++i) {
LOGI("线程 %d 写入的日志消息 %d 时间戳: %ld", threadId, i, std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()));
}
}
void readLogs(const std::string &logFile, int numReads){
for (int i = 0; i < numReads; ++i) {
std::ifstream ifs(logFile);
if (!ifs.is_open()) {
LOGE("无法打开日志文件进行读取: %s", logFile.c_str());
return;
}
std::string line;
while (std::getline(ifs, line)) {
// 模拟读取操作,可以在实际使用时处理或输出日志内容// LOGI("读取的日志内容: %s", line.c_str()); // 如果需要打印读取内容,可以启用这行
}
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟读取间隔
}
}
int main(){
const std::string logFile = "test_logs.txt";
const int numMessages = 1000;
const int numReads = 100;
// 使用 GlobalLoggerBuilder 初始化日志系统
bitlog::GlobalLoggerBuilder::ptr lbp(new bitlog::GlobalLoggerBuilder);
lbp->buildLoggerName("test_logger");
lbp->buildLoggerLevel(bitlog::LogLevel::value::INFO); // 确保设置正确的日志级别
lbp->buildFormatter("%m");
lbp->buildSink<bitlog::FileSink>(logFile); // 设置日志输出文件为 test_logs.txt
lbp->buildLoggerType(bitlog::Logger::Type::LOGGER_SYNC); // 使用同步日志器
lbp->build();
// 创建写入和读取线程
std::thread writer1(writeLogs, numMessages, 1);
std::thread writer2(writeLogs, numMessages, 2);
std::thread reader(readLogs, logFile, numReads);
// 等待所有线程完成
writer1.join();
writer2.join();
reader.join();
LOGI("日志写入与读取测试完成。");
return 0;
}