之前有一篇博客已经讲解了如何用protobuf+socket完成心跳包的具体过程,见 protobuf+socket实现CS之间的心跳包. 显然之前并没有用到所谓的rpc的调用功能,只是利用protobuf实现序列化的反序列化的功能。
这几天,在学习了brpc开源提供的一些案例的时候,尝试着用brcp去实现cs之间的心跳包,具体的过程如下:
brpc的开源例子见链接:https://github.com/brpc/brpc/tree/master/example/echo_c%2B%2B
1.定制心跳包
由于brpc使用的底层序列化工具是protobuf,所以定制的心跳包也是按照protobuf提供的proto文件来定义,具体定义如下:
syntax="proto2";
package heart; //定义包名
option cc_generic_services = true;
//定义请求心跳包形式
message HeartRequest{
required string message = 1;
}
//定义响应心跳包形式
message HeartResponse{
required string message = 1;
}
//定义心跳服务,主要是接收心跳请求,然后返回当前状态
service HeartService{
rpc HeartRpc(HeartRequest) returns (HeartResponse);
}
2. 客户端代码
同样是CS架构,首先是客户端代码,客户端向服务端调用心跳请求服务,客户端提供的框架基本如下:
1.通过gflags进行命令行配置的转换,并定义默认项(gflags具体使用方法可以参考博文google gflags 库完全使用)
2.定义一个channel,brpc中没有客户端的概念,客户端可以认为是一个channel,连接到服务端的channel.
3.设置channel的一些参数,比如使用的上层协议,连接方式,超时延时,重试次数等等
4.开启这个channel,利用gflags来配置channel对应的ip地址端口号
5.为protobuf的服务设置一个桩函数stub,通过这个桩函数调用服务(实际通过这个桩函数调用的服务都会由protobuf接管,将参数等数据发送到服务端)
6.填充数据包,set_message()
7.设置controller,这里controller就是brpc提出的控制器,负责在整个rpc调用过程中的性能以及其他参数的控制功能。你可以给这个controller设置携带的附件,设置需要监控的延时选项等等。
8.设置回调函数,注意本案例是同步调用,所以不是异步,不用设置回调函数,如果异步的调用,需要设置对应的回调函数done()
9.打印接收信息
基本是按照上述的9个步骤完成客户端代码的撰写,在整个代码的过程中,你可以发现根本不需要去理会网络协议,socket这些,你只需要专心自己的功能逻辑,需要远程调用的时候去调用即可。
代码如下:
#include <gflags/gflags.h>
#include <butil/logging.h>
#include <butil/time.h>
#include <brpc/channel.h>
#include "heart_package.pb.h"
//using gflags to define line input_iterator_tag
DEFINE_string(attachment,"this is attachment","Carry this along with requests");
DEFINE_string(protocol,"baidu_std","Protocol type.Define in src/brpc/option.proto");
DEFINE_string(connection_type,"","Connection type. Available value:single,polled,short");
DEFINE_string(server,"0.0.0.0:8000","IP Address of service");
DEFINE_string(load_balancer,"","The algorithm for load balancing");
DEFINE_int32(timeout_ms,100,"RPC timeout in milliseconds");
DEFINE_int32(max_retry,3,"Max retries(not including the first rpc)");
DEFINE_int32(interval_ms,1000,"Milliseconds between consecutive requests");
int main(int argc, char* argv[])
{
//1. prase gflags.
GFLAGS_NS::ParseCommandLineFlags(&argc,&argv,true);
//2.define a channel
brpc::Channel channel;
//3.set the channel options
brpc::ChannelOptions options;
options.protocol = FLAGS_protocol;
options.connection_type = FLAGS_connection_type;
options.timeout_ms = FLAGS_timeout_ms;
options.max_retry = FLAGS_max_retry;
//4. and initialize the channel
if(channel.Init(FLAGS_server.c_str(),FLAGS_load_balancer.c_str(),&options) !=0){
LOG(ERROR) << "Fail to initialize channel";
return -1;
}
//5.creat a service_stub and call a channel by stub
heart::HeartService_Stub stub(&channel);
int log_id =