brpc的简单使用

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


前言

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


大体流程

Rpc调用实现样例:
服务端:
1.创建rpc服务子类继承pb中的EchoService服务类,并实现内部的业务接口逻辑
2.创建rpc服务器类,搭建服务器
3. 向服务器类中添加 rpc子服务对象 – 告诉服务器收到什么请求用哪个接口处理
4.启动服务器
客户端:
1.创建网络通信信道
2.实例化pb中的EchoService Stub类对象
3.发起rpc请求,获取响应进行处理

一、编写.proto文件

定义两个message结构体 代表请求和响应。
定义一个servicer 服务。
使用 protoc --cpp_out./ main生成.cc和.h文件

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方法。

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.构造服务器对象

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

brpc::Server server;

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

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

 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的线程数量等。

 //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对象,

	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调用

example::EchoService_Stub stub(&channel);

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

同步调用Echo会阻塞等待响应的返回。
同样的,在客户端的调用中也有四个参数。
第一个参数Controller是用于判断请求是否Ok.
第四个参数就不同了,在服务器中第四个参数是为了告知brpc业务已经处理完毕,可以进行返回响应。客户端的第四个参数主要是为了支持异步调用。

    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在堆上创建。

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));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值