
#RPC#据说brpc性能强悍,功能完整。这里体验下。

bRPC官网
本文结合介绍如何在Ubuntu下基于源码构建bRPC,并基于C++开发开发服务端和客户端应用。
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 24.04.3 LTS
Release: 24.04
Codename: noble
下载bRPC依赖的工具与第三方库
# M 更新软件源缓存
sudo apt update
# M 安装brpc依赖
sudo apt-get install -y git g++ make libssl-dev libgflags-dev libprotobuf-dev libprotoc-dev protobuf-compiler libleveldb-dev
# M 安装glog,否则一些例子程序跑不起来
sudo apt install -y libgoogle-glog-dev
# O 静态连接leveldb
sudo apt-get install -y libsnappy-dev
# O 启用profile
sudo apt-get install -y libgoogle-perftools-dev
# O 运行测试
sudo apt-get install -y cmake libgtest-dev && cd /usr/src/gtest && sudo cmake . && sudo make && sudo mv lib/libgtest* /usr/lib/ && cd -
下载源码,执行构建
# 可直接官网下载最新版本的源码包apache-brpc-1.14.1-src
wget https://dlcdn.apache.org/brpc/1.14.1/apache-brpc-1.14.1-src.tar.gz
tar zxvf apache-brpc-1.14.1-src.tar.gz
cd apache-brpc-1.14.1-src
cmake -B build -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DWITH_GLOG=ON -DWITH_GLOG=ON
cmake --build build/
# 安装到特定目录
mkdir ~/soft/brpc
cp -r buid/output/* ~/soft/brpc/
进入例子程序
cd example/echo_c++/
cmake -B build && cmake --build build
# 运行服务
./build/echo_server &
# 运行客户端
./build/echo_client$ cat test.proto
syntax = "proto3";
package Test;
option cc_generic_services = true;
service TestService {
rpc runTest (TestRequest) returns (TestResponse);
}
message TestRequest {
string message = 1;
int32 msg_type = 2; // 新增:消息类型(如1-磁盘,2-网络,3-CPU,4-内存)
}
message TestResponse {
string response = 1;
int32 status_code = 2; // 新增:处理状态(如0-成功,1-失败)
}
$ cat src/server.cpp
#include <iostream>
#include <brpc/server.h>
#include <butil/logging.h> // BRPC 日志头文件
#include "test.pb.h"
class TestServiceImpl : public Test::TestService {
public:
TestServiceImpl() = default;
~TestServiceImpl() = default;
void runTest(google::protobuf::RpcController* cntl_base,
const Test::TestRequest* request,
Test::TestResponse* response,
google::protobuf::Closure* done) override {
brpc::ClosureGuard done_guard(done);
brpc::Controller* cntl = static_cast<brpc::Controller*>(cntl_base);
// 获取请求参数
std::string message = request->message();
int32_t msg_type = request->msg_type();
// 根据消息类型处理业务逻辑
std::string processed_message;
int32_t status_code = 0;
switch (msg_type) {
case 1: // 磁盘测试
processed_message = "[磁盘测试] 处理: " + message;
break;
case 2: // 网络测试
processed_message = "[网络测试] 处理: " + message;
break;
case 3: // CPU测试
processed_message = "[CPU测试] 处理: " + message;
break;
case 4: // 内存测试
processed_message = "[内存测试] 处理: " + message;
break;
default:
processed_message = "[未知类型] 处理: " + message;
status_code = 1; // 失败状态
break;
}
// 设置响应
response->set_response(processed_message);
response->set_status_code(status_code);
// 打印日志 - 使用 BRPC 的 LOG 宏
LOG(INFO) << "收到请求: message=" << message
<< ", msg_type=" << msg_type
<< ", 返回: " << processed_message
<< ", 状态: " << (status_code == 0 ? "成功" : "失败");
}
};
int main(int argc, char* argv[]) {
// 方案1: 完全移除日志初始化代码(使用默认配置)
// BRPC 默认会输出到 stderr,对于开发测试一般足够
// 方案2: 使用更简单的日志配置(如果的确 需要)
// 设置日志级别为 WARNING 以减少输出
// 初始化 glog 日志系统(必须在设置日志级别之前)
google::InitGoogleLogging(argv[0]); // 新增这一行
//if (google::SetCommandLineOption("log_level", "2").empty()) {
// minloglevel=1 表明只输出 WARNING 及以上级别日志(0=INFO,1=WARNING,2=ERROR,3=FATAL),更符合你的需求。
if (google::SetCommandLineOption("minloglevel", "0").empty()) { // 1 对应 WARNING
std::cerr << "设置日志级别失败" << std::endl;
}
// 创建服务器
brpc::Server server;
TestServiceImpl test_service;
// 添加服务
if (server.AddService(&test_service, brpc::SERVER_DOESNT_OWN_SERVICE) != 0) {
std::cerr << "添加服务失败!" << std::endl;
return -1;
}
// 服务器配置
brpc::ServerOptions options;
options.idle_timeout_sec = -1; // 连接永不超时
options.num_threads = 4; // IO线程数
// 启动服务器(端口8000)
if (server.Start(8000, &options) != 0) {
std::cerr << "启动服务器失败!" << std::endl;
return -1;
}
std::cout << "测试服务器运行在端口 8000..." << std::endl;
// 等待直到收到停止信号
server.RunUntilAskedToQuit();
return 0;
}
$ cat src/client.cpp
#include <iostream>
#include <brpc/channel.h>
#include "test.pb.h"
int main(int argc, char* argv[]) {
// 检查参数
if (argc < 3) {
std::cerr << "用法: " << argv[0] << " <消息> <类型[1-4]>" << std::endl;
std::cerr << "类型说明: 1-磁盘, 2-网络, 3-CPU, 4-内存" << std::endl;
return -1;
}
std::string message = argv[1];
int32_t msg_type = std::stoi(argv[2]);
// 初始化通道
brpc::Channel channel;
brpc::ChannelOptions options;
options.protocol = "baidu_std";
options.timeout_ms = 1000; // 1秒超时
options.max_retry = 3;
// 连接服务器
if (channel.Init("127.0.0.1:8000", &options) != 0) {
std::cerr << "连接服务器失败!" << std::endl;
return -1;
}
// 创建存根
Test::TestService_Stub stub(&channel);
// 准备请求和响应
Test::TestRequest request;
Test::TestResponse response;
brpc::Controller cntl;
// 设置请求参数
request.set_message(message);
request.set_msg_type(msg_type);
// 发起RPC调用
stub.runTest(&cntl, &request, &response, nullptr);
// 处理响应
if (!cntl.Failed()) {
std::cout << "响应: " << response.response() << std::endl;
std::cout << "状态码: " << response.status_code()
<< " (" << (response.status_code() == 0 ? "成功" : "失败") << ")" << std::endl;
std::cout << "延迟: " << cntl.latency_us() << "us" << std::endl;
} else {
std::cerr << "RPC调用失败: " << cntl.ErrorText() << std::endl;
return -1;
}
return 0;
}
$ cat CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(test_brpc_project C CXX)
# 设置C++标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 固定依赖库路径(请根据您的实际安装路径修改)
set(BRPC_INCLUDE_DIR "/home/release/soft/brpc/include")
set(BRPC_LIB_DIR "/home/release/soft/brpc/lib")
set(PROTOBUF_INCLUDE_DIR "/usr/include")
set(PROTOBUF_LIB_DIR "/usr/lib")
set(LEVELDB_INCLUDE_DIR "/usr/include")
set(LEVELDB_LIB_DIR "/usr/lib")
# 包含目录
include_directories(
${PROJECT_SOURCE_DIR}
${BRPC_INCLUDE_DIR}
${PROTOBUF_INCLUDE_DIR}
${LEVELDB_INCLUDE_DIR}
)
# 链接目录
link_directories(
${BRPC_LIB_DIR}
${PROTOBUF_LIB_DIR}
${LEVELDB_LIB_DIR}
)
# 生成protobuf文件
include(FindThreads) # 加载 CMake 内置模块,用于查找系统线程库(pthread)
include(FindProtobuf) # 加载 CMake 内置模块,用于查找 Protobuf 库
protobuf_generate_cpp(PROTO_SRC PROTO_HEADER idl/test.proto) # 编译 proto 文件:生成 C++ 源码(PROTO_SRC)和头文件(PROTO_HEADER)
include_directories(${CMAKE_CURRENT_BINARY_DIR}) # 将 proto 生成文件的目录(编译目录)添加到头文件搜索路径
# 服务器可执行文件
add_executable(test_server
src/server.cpp
${PROTO_SRC} ${PROTO_HEADER}
)
# 客户端可执行文件
add_executable(test_client
src/client.cpp
${PROTO_SRC} ${PROTO_HEADER}
)
# 链接库(固定库名称)
target_link_libraries(test_server
brpc
gflags
glog
unwind
protobuf
leveldb
ssl
crypto
pthread
dl
z
)
target_link_libraries(test_client
brpc
gflags
glog
unwind
protobuf
leveldb
ssl
crypto
pthread
dl
z
)
$ ./build/test_server
测试服务器运行在端口 8000...
$ ./build/test_client aa 1
响应: [磁盘测试] 处理: aa
状态码: 0 (成功)
延迟: 2272us
# 停止服务
killall test_server
rpc_press --proto=../idl/test.proto --method=Test.TestService.runTest --input config.json
rpc_press --proto=./test.proto --method=Test.TestService.runTest --input message.json --server 172.21.165.94:9000 --thread_num=30 --qps=5000查看config.json
{
"message":"12345678901234561234567890123456123456789012345612345678901234561234567890123456123456789012345612345678901234561234567890123456123456789012345612345678901234561234567890123456123456789012345612345678901234561234567890123456123456789012345612345678901234561234567890123456123456789012345612345678901234561234567890123456123456789012345612345678901234561234567890123456123456789012345612345678901234561234567890123456123456789012345612345678901234561234567890123456123456789012345612345678901234561234567890123456",
"msg_type":2
}
最好基于源码和自定义路径安装protobuf库,否则一旦有问题,清理起来极为麻烦。