Ubuntu22.04 - brpc的安装和使用

目录

介绍

brpc 是用 c++语言编写的工业级 RPC 框架,常用于搜索、存储、机器学习、广告、推荐等高性能系统

安装

先安装依赖
apt-get install -y git g++ make libssl-dev libprotobuf-dev libprotoc-dev protobuf-compiler libleveldb-dev libgflags-dev
安装brpc

去github上下载https://github.com/apache/brpc.git

依次执行
unzip brpc-master.zip
cd brpc-master
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr .. && cmake --build . -j6
make && sudo make install

使用

示例:

main.proto文件

复制代码
syntax="proto3";

package example;

option cc_generic_services = true;  // 这个选项的功能其实就是 生成框架代码的时候, 内部包含了rpc相关接口的内容

message EchoRequest{
    string message = 1;
}

message EchoResponse{
    string message = 1;
}

//这是回显服务器的名称
service EchoService{
    // EchoRequest参数      EchoResponse返回类型
    rpc Echo(EchoRequest) returns (EchoResponse);   // 定义rpc接口
}

client.cc文件

复制代码
#include <brpc/channel.h>
#include <thread>
#include "main.pb.h"

//brpc是同步调用还是异步调用, 是客户端来决定的  -- 明天ai问一下

void callback(brpc::Controller* cntl, ::example::EchoResponse* response){
    std::unique_ptr<brpc::Controller> cntl_guard(cntl);
    std::unique_ptr<example::EchoResponse> resp_guard(response);
    if (cntl->Failed() == true) {
        std::cout << "Rpc调用失败: " << cntl->ErrorText() << std::endl;
        return;
    }
    std::cout << "收到响应: " << response->message() << std::endl;
}

int main(int argc, char* argv[])
{
    //1. 构造Channel信道, 连接服务器
    brpc::ChannelOptions options;
    options.connect_timeout_ms = -1;    //连接等待超时时间, -1表示一直等待
    options.timeout_ms = -1;        //rpc请求等待超时时间, -1表示一直等待
    options.protocol = "baidu_std"; //序列化协议, 默认使用baidu_std
    brpc::Channel channel;  //为什么要有这个类? 没有这个类就不能进行通信, 理解为管道 
    int ret = channel.Init("127.0.0.1:8080", &options); //参数1: 服务器地址  参数2: 客户端连接时的配置
    if (ret == -1) {
        std::cout << "初始化信道失败! \n";
        return -1;
    }

    //2. 构造EchoService_Stub对象, 用于进行rpc调用
    example::EchoService_Stub stub(&channel);   //相当于客户端类
    //3. 进行Rpc调用
    example::EchoRequest req;
    req.set_message("你好~比特~!");


    //这个Controller提供了很多功能, 其中一个就是辨别返回值的成功或失败
    brpc::Controller* cntl = new brpc::Controller();
    //如果我们不想同步处理, 即不想等待响应, 希望异步, 就要通过Controller设置回调函数
    //注意一个问题: 可能在处理回调函数的时候,如果这个cntl和rsp是栈对象 这个cntl,rsp会被释放掉, 如果这个main函数
    //是一个普通的函数,则处理这个回调函数的时候,可能这个函数已经结束了, 这个cntl,rsp已经被释放掉了,这就可能出现错误

    example::EchoResponse* rsp = new example::EchoResponse();  //用于接收返回值的
    auto clusure = google::protobuf::NewCallback(callback, cntl, rsp);
    stub.Echo(cntl, &req, rsp, clusure);    //异步调用
    // stub.Echo(cntl, &req, rsp, nullptr);      //最后一个参数, 如果是异步调用, 则要传参让服务器设置去run, 我们是同步调用, 所以就不用设置了
    // if(cntl->Failed() == true) {
    //     std::cout << "Rpc调用失败: " << cntl->ErrorText() << std::endl;
    //     return -1;
    // }
    // std::cout << "收到响应: " << rsp->message() << std::endl;

    std::this_thread::sleep_for(std::chrono::seconds(3));
    return 0;   //如果是异步调用, 主函数需要等待, 否则程序可能会直接结束
}

server.cc文件

复制代码
#include <brpc/server.h>
#include <butil/logging.h>
#include "main.pb.h"

//1. 继承与EchoService创建一个子类, 并实现rpc调用的业务功能
class EchoServiceImpl : public example::EchoService{     //EchoService类是远程调用rpc服务的类 - 就是真正进行sum计算的
    public:
    // 重写这个虚函数
    //RpcController: 返回结果是成功或失败   
    //request客户端的请求   response服务器要构造的响应
    //Closure: 大格局理解 服务端是异步执行的, 将Response的响应设置完了, 再调用run函数, 告诉服务器可以发给客户端响应了
    void Echo(google::protobuf::RpcController* controller, const ::example::EchoRequest* request,
              ::example::EchoResponse* response, ::google::protobuf::Closure* done) //至于这个函数是在业务服务器 主线程还是线程池中执行, 我们并不关心
    {
        //防止程序员忘记最后调用run函数, 所以用智能指针来管理起来
        brpc::ClosureGuard rpc_guard(done);
        std::cout << "收到消息:" << request->message() << std::endl;

        std::string str = request->message() + "--这是响应!!";
        response->set_message(str);
        // done->Run()      如果不写上面的guard, 则需要加上这句话
    }
};

int main(int argc, char* argv[])
{
    // 关闭brpc的默认日志输出
    logging::LoggingSettings settings;
    settings.logging_dest = logging::LoggingDestination::LOG_TO_NONE;
    logging::InitLogging(settings);
    //2. 构造服务器对象
    brpc::Server server;
    
    //3. 向服务器对象中, 新增EchoService服务
    EchoServiceImpl echo_service;
    int ret = server.AddService(&echo_service, brpc::ServiceOwnership::SERVER_DOESNT_OWN_SERVICE);
    if (ret == -1){
        std::cout << "添加Rpc服务失败!\n";
        return -1;
    }
    //参数1: 添加服务, 只有你添加了服务, 服务器才能处理你对应的请求, 和路由很像    类型为Service*, EchoServiceImpl是它的子类
    //参数2: 添加服务失败的时候, 服务器是否会删除该对象  因为echo_service是局部变量, 所以不用去释放

    //4. 启动服务器
    brpc::ServerOptions options;    //启动服务器时的配置类
    options.idle_timeout_sec = -1;  //连接空闲超时时间 - 超时后连接被关闭
    options.num_threads = 1;        //io线程数量
    ret = server.Start(8080, &options);
    if (ret == -1) {
        std::cout << "启动服务器失败! \n";
        return -1;
    }
    server.RunUntilAskedToQuit();   //服务器一直循环运行
    return 0;
}

先用protoc进行编译:

编译运行:


相关推荐
西岸行者13 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意13 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码13 天前
嵌入式学习路线
学习
毛小茛13 天前
计算机系统概论——校验码
学习
babe小鑫13 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms13 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下13 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。13 天前
2026.2.25监控学习
学习
im_AMBER13 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J13 天前
从“Hello World“ 开始 C++
c语言·c++·学习