How to use baidu-rpc(Hello brpc)

百度内最常使用的工业级RPC框架, 有1,000,000+个实例(不包含client)和上千种多种服务, 在百度内叫做“baidu-rpc”. 目前只开源C++版本。 https://github.com/brpc/brpc/blob/master/README_cn.md ### 运行brpc/example/echo_c++ 按照 https://github.com/brpc/brpc/blob/master/docs/cn/getting_started.md 配置好protobufbrpc环境。

$ sudo apt-get install git g++ make libssl-dev
$ sudo apt-get install libgflags-dev libprotobuf-dev libprotoc-dev protobuf-compiler libleveldb-dev

OK,是时候,跑一下DEMO程序了...

$ sh config_brpc.sh --headers=/usr/include --libs=/usr/lib
$ make
$ cd example/echo_c++
$ make
$ ./echo_server &
$ ./echo_client


那么,自己再动手写一个依赖于brpc通信的程序试试。推荐先阅读《Google Protocol Buffer Basics: C++》


hellobrpc项目结构

整个项目包括三部分:Google Protocol Buffer文件、客户端client.cpp和服务端server.cpp

.
└── hellobrpc
├── client.cpp
├── CMakeLists.txt
├── hello.pb.cc
├── hello.pb.h
├── proto
│   └── hello.proto
└── server.cpp

proto/hello.proto

定义好通信格式,serviceprotobuf中专门对rpc的支持,见《Defining Services》cc_generic_services表示让protoc编译器生成基于cc语法的rpc服务抽象代码(另外还有java_generic_servicespy_generic_services等)。

syntax="proto2";
package hellobrpc;

option cc_generic_services = true;

message HelloRequest {
required string msg = 1;
};

message HelloResponse {
required string msg = 1;
};

service HelloService {
rpc Hello(HelloRequest) returns (HelloResponse);
};

server.cpp

服务端,使用者需要继承HelloService类并override其纯虚函数Hello。这里的HelloService类位于hello.pb.h中,由protoc编译器根据.proto中的service自动生成。brpc操作,见main函数。更多参考, https://github.com/brpc/brpc/blob/9f4c192028891d63ebb0c287f60be9d2313b60ed/docs/cn/server.md https://github.com/brpc/brpc/blob/master/example/echo_c++/server.cpp

#include <iostream>
#include <gflags/gflags.h>
#include <brpc/server.h>
#include "hello.pb.h"

namespace hellobrpc{
class HelloServiceImpl : public HelloService{
public:
HelloServiceImpl(){
}
virtual ~HelloServiceImpl(){
}

virtual void Hello(::google::protobuf::RpcController* controller,
const ::hellobrpc::HelloRequest* request,
::hellobrpc::HelloResponse* response,
::google::protobuf::Closure* done){
brpc::ClosureGuard done_guard(done);
std::cout << request->msg() << std::endl;
response->set_msg("Hi brpc");
}
};
}

int main(){
brpc::Server server;
hellobrpc::HelloServiceImpl hello_service_impl;
server.AddService(&hello_service_impl, brpc::SERVER_DOESNT_OWN_SERVICE);

brpc::ServerOptions options;
server.Start(9527, &options);
server.RunUntilAskedToQuit();

return 0;
}

client.cpp

定义channelHelloService_Stub。然后,通过request设置发送数据内容,并由stub桩发送。最后,使用response获取远程的回复的数据结果。更多参见, https://github.com/brpc/brpc/blob/master/docs/cn/client.md https://github.com/brpc/brpc/blob/master/example/echo_c++/client.cpp

#include <iostream>
#include <gflags/gflags.h>
#include <brpc/channel.h>
#include "hello.pb.h"

int main(){
brpc::Channel channel;
brpc::ChannelOptions options;

channel.Init("0.0.0.0",9527, NULL);
hellobrpc::HelloService_Stub stub(&channel);

hellobrpc::HelloRequest request;
hellobrpc::HelloResponse response;
brpc::Controller cntl;

request.set_msg("Hello brpc");
stub.Hello(&cntl, &request, &response, NULL);

if (!cntl.Failed()){
std::cout << response.msg() << std::endl;
}

return 0;
}

CMakeLists.txt

直接使用brpc提供的CMakeLists.txt文件,简单修改一下,符合自己的要求就OK了。官方CMakeLists.txt如下 https://github.com/brpc/brpc/blob/master/example/echo_c%2B%2B/CMakeLists.txt 本文只更改了几处,第一处为修改了项目名为hellobrpc C CXX。第二处为,修改了brpc路径如下。

execute_process(
COMMAND bash -c "find ${PROJECT_SOURCE_DIR}/../brpc -type d -regex \".*output/include$\" | head -n1 | xargs dirname | tr -d '\n'"
OUTPUT_VARIABLE OUTPUT_PATH
)

第三处,设置自己的.proto文件路径。

protobuf_generate_cpp(PROTO_SRC PROTO_HEADER proto/hello.proto)

第四处,将自己新增的.cpp添加并链接生成可执行文件。

add_executable(hello_client client.cpp ${PROTO_SRC} ${PROTO_HEADER})
add_executable(hello_server server.cpp ${PROTO_SRC} ${PROTO_HEADER})

编译、运行

首先编译、链接,生成可执行文件hello_clienthello_server

$ cd hellobrpc
$ cmake .
$ make

运行服务端

$ ./hello_server
I1115 23:49:59.653273 33345 src/brpc/server.cpp:1037] Server[hellobrpc::HelloServiceImpl] is serving on port=9527.
I1115 23:49:59.653646 33345 src/brpc/server.cpp:1040] Check out http://ubuntu:9527 in web browser.

新启一个终端运行客户端。客户端发送Hello brpc至服务端,并等待。一段时间后,获得服务端返回的结果Hi brpc

$ ./hello_client 
Hi brpc

服务端收到来自客户端的Hello brpc消息,并马上回复了Hi brpc给客户端。

$ ./hello_server
I1115 23:49:59.653273 33345 src/brpc/server.cpp:1037] Server[hellobrpc::HelloServiceImpl] is serving on port=9527.
I1115 23:49:59.653646 33345 src/brpc/server.cpp:1040] Check out http://ubuntu:9527 in web browser.
Hello brpc

此时可以在 http://ubuntu:9527 查看可视化结果...

References: [1] https://github.com/brpc/brpc/blob/master/README_cn.md [2] https://developers.google.com/protocol-buffers/docs/proto#services [3] https://blog.csdn.net/breaksoftware/article/details/81564405 [4] https://github.com/brpc/brpc/blob/master/docs/cn/brpc_intro.pptx