brpc的简单使用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

使用brpc简单搭建一个echo服务。


大体流程

Rpc调用实现样例:

服务端:

1.创建rpc服务子类继承pb中的EchoService服务类,并实现内部的业务接口逻辑

2.创建rpc服务器类,搭建服务器

  1. 向服务器类中添加 rpc子服务对象 -- 告诉服务器收到什么请求用哪个接口处理

4.启动服务器

客户端:

1.创建网络通信信道

2.实例化pb中的EchoService Stub类对象

3.发起rpc请求,获取响应进行处理

一、编写.proto文件

定义两个message结构体 代表请求和响应。

定义一个servicer 服务。

使用 protoc --cpp_out./ main生成.cc和.h文件

cpp 复制代码
syntax="proto3";

package example;

option cc_generic_services = true;

message EchoRequest{
    string message = 1;
}

message EchoResponse{
    string message = 1;
}

service EchoService{
    rpc Echo(EchoRequest) returns (EchoResponse);
}

二、服务端搭建

1.继承EchoService创建一个子类,并重写业务方法

重写的方法就是.proto文件中声明的,这个方法有四个参数,req和resp就不解释了,从req中获取数据,进行业务处理,并把结果写入到resp中。

其中,第一个参数RpcController,这是一个上下文管理类,主要是用来判断请求是否ok。

而第四个参数Closure,在服务器端当响应处理完毕后,需要显示效用这个类中run方法,告诉brpc响应已经处理完了,结果已经写入到resp中,可以给客户端进行响应了。

而为了防止用户忘记调用run,我们可以使用ClosureGuard来管理这个closure对象,他会帮我们调用run方法。

cpp 复制代码
class EchoServiceImpl : public example::EchoService{
public:
    EchoServiceImpl(){}
    ~EchoServiceImpl(){}

    //重写Echo方法
    void Echo(google::protobuf::RpcController* controller,
                         const ::example::EchoRequest* request,
                         ::example::EchoResponse* response,
                         ::google::protobuf::Closure* done){
        
        brpc::ClosureGuard rpc_guard(done);
        std::cout << "收到消息:" << request->message() << std::endl;

        std::string str = request->message() + "--这是响应!!";
        response->set_message(str);
    }
};

2.构造服务器对象

构造一个服务器用于网络通信。

cpp 复制代码
brpc::Server server;

3.向服务器对象中,新增EchoService服务

将Echoservice服务注册进服务器中,当指定的服务请求到来时,调用指定的服务处理函数,这里的SERVER_DOESNT_OWN_SERVICE代表服务添加失败后,服务器不帮忙释放这个对象。

cpp 复制代码
 EchoServiceImpl echo_service;
    int ret = server.AddService(&echo_service,brpc::ServiceOwnership::SERVER_DOESNT_OWN_SERVICE);
    if (ret == -1) {
        std::cout << "添加Rpc服务失败!\n";
        return -1;
    }

4.启动服务器

启动服务器需要填写监听端口和一个ServerOptions对象.

这个对象主要是设置服务器相关选项,多长时未发送连接相关活动就断开连接,io的线程数量等。

cpp 复制代码
 //4.启动服务器
    brpc::ServerOptions options;
    options.idle_timeout_sec = -1;  //多长时间没有连接相关事件则关闭连接 -1为永不关闭
    options.num_threads = 1;    //io线程数量
    ret = server.Start(8085,&options);
    if (ret == -1) {
        std::cout << "添加Rpc服务失败!\n";
        return -1;
    }
    server.RunUntilAskedToQuit();// 运行服务器,直到请求退出

三、客户端搭建

1.构造Channel信道,连接服务器

brpc对连接进行了更细粒度的划分,在一个连接上可以建立多个信道,而多个信道他们底层使用的是同一个连接。用户只需要使用channel来与服务器通信,从而抽象了网络细节。

同样的在与服务器建立连接时,也需要传入一个Channeloptions对象,

cpp 复制代码
	brpc::ChannelOptions options;
	options.connect_timeout_ms = -1;    //连接超时时间
	options.timeout_ms = -1;    //请求超时时间
	options.max_retry = 3;  //最大重传次数
	options.protocol = "baidu_std"; //网络通信协议
	brpc::Channel channel;
	int ret = channel.Init("127.0.0.1:8085",&options);
	if (ret == -1) {
	    std::cout << "初始化信道失败!\n";
	    return -1;
    }

2.构造存根对象,用于rpc调用

cpp 复制代码
example::EchoService_Stub stub(&channel);

3.进行rpc调用 --同步调用

同步调用Echo会阻塞等待响应的返回。

同样的,在客户端的调用中也有四个参数。

第一个参数Controller是用于判断请求是否Ok.

第四个参数就不同了,在服务器中第四个参数是为了告知brpc业务已经处理完毕,可以进行返回响应。客户端的第四个参数主要是为了支持异步调用。

cpp 复制代码
    example::EchoRequest req;
    req.set_message("你好,lkm");
    example::EchoResponse resp;
    brpc::Controller cntl;
    stub.Echo(&cntl,&req,&resp,nullptr);
    if(cntl.Failed() == true){
        std::cout << "Rpc调用失败:" << cntl.ErrorText() << std::endl;
        return -1;
    }
    std::cout << "收到响应: " << resp.message() << std::endl;

4.异步调用

第四个参数是一个Closure对象,它可以设置一个回调函数,当响应返回后调用设置的回调函数进行处理。

需要注意的是,由于Echo现在是异步调用,所有他在调用完后就会立即返回,所以为了防止作用域问题,我们需要把resp和Controller在堆上创建。

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

 example::EchoRequest req;
    req.set_message("你好,lkm");
    example::EchoResponse *resp = new example::EchoResponse();
    brpc::Controller *cntl = new brpc::Controller();
    google::protobuf::Closure* closure = google::protobuf::NewCallback(callback,cntl,resp);   //这里设置回调函数
    stub.Echo(cntl,&req,resp,closure);

    std::cout << "rpc调用请求已发送" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(3));
相关推荐
喝旺仔la4 分钟前
VSCode的使用
java·开发语言·javascript
qing_04060314 分钟前
C++——模板初阶
开发语言·c++·模板
YOLO数据集工作室26 分钟前
Python介绍
开发语言·python
多思考少编码27 分钟前
【LGR-200-Div.4】洛谷入门赛 #27 A - H题解,包含(C++, Go语言)
开发语言·c++·golang·洛谷·算法竞赛
尘浮生32 分钟前
Java项目实战II基于Java+Spring Boot+MySQL的大型商场应急预案管理系统(源码+数据库+文档)
java·开发语言·数据库·spring boot·spring·maven·intellij-idea
一水鉴天40 分钟前
智能工厂的软件设计 “程序program”表达式,即 接口模型的代理模式表达式
开发语言·人工智能·中间件·代理模式
蒙娜丽宁44 分钟前
深入理解Go语言中的接口定义与使用
开发语言·后端·golang·go
尘浮生1 小时前
Java项目实战II基于Java+Spring Boot+MySQL的校园社团信息管理系统(源码+数据库+文档)
java·开发语言·数据库·spring boot·mysql·spring·maven
qq_1873526341 小时前
马踏棋盘c++
开发语言·c++·马踏棋盘c++
巭犇2 小时前
c语言中define使用方法
c语言·开发语言