sofa-pbrpc开源地址: https://github.com/baidu/sofa-pbrpcpython
sofa-pbrpc高级用法包括:c++
sofa-pbrpc-clienta-pbrpc支持三个级别的超时控制,按照生效的优先级由高到低依次为:git
在proto文件中指定“method超时”和“Service超时”的样例以下:github
import "sofa/pbrpc/rpc_option.proto"; package sofa.pbrpc.test; option cc_generic_services = true; message SleepRequest { required int32 sleep_time = 1; // in seconds } message SleepResponse { required string message = 1; } service SleepServer { // The service timeout is 2 seconds. option (sofa.pbrpc.service_timeout) = 2000; rpc SleepWithServiceTimeout(SleepRequest) returns(SleepResponse); // The method timeout is 4 seconds. rpc SleepWithMethodTimeout(SleepRequest) returns(SleepResponse) { option (sofa.pbrpc.method_timeout) = 4000; } }
注意:shell
若是在proto中指定超时,须要import "sofa/pbrpc/rpc_option.proto",而且编译proto文件时还须要添加protobuf头文件路径到proto_path中,具体可参考样例“sample/timeout_sample”;json
RpcController中设置超时时间的接口以下:网络
void SetTimeout(int64 timeout_in_ms);
sofa-pbrpc支持两个级别的数据压缩控制,按照生效优先级由高到低依次为:app
目前支持的压缩类型包括:负载均衡
在proto文件中指定压缩类型的样例以下:curl
import "sofa/pbrpc/rpc_option.proto"; package sofa.pbrpc.test; option cc_generic_services = true; message EchoRequest { required string message = 1; } message EchoResponse { required string message = 1; } service EchoServer { rpc Echo(EchoRequest) returns(EchoResponse) { option (sofa.pbrpc.request_compress_type) = CompressTypeGzip; option (sofa.pbrpc.response_compress_type) = CompressTypeGzip; } }
RpcController中设置压缩类型的接口以下:
// Set compress type of the request message. // Supported types: // CompressTypeNone // CompressTypeGzip // CompressTypeZlib // CompressTypeSnappy // CompressTypeLZ4 void SetRequestCompressType(CompressType compress_type); // Set expected compress type of the response message. // Supported types: // CompressTypeNone // CompressTypeGzip // CompressTypeZlib // CompressTypeSnappy // CompressTypeLZ4 void SetResponseCompressType(CompressType compress_type);
sofa-pbrpc支持在RpcServer和RpcClient级别在Options中指定参数就能够控制网络带宽限制,包括“出带宽”、“入带宽”,使流量控制对应用层透明,简化应用层的工做。 在RpcServerOptions和RpcClientOptions中能够分别指定Server端和Client端的最大入带宽“max_throughput_in”和最大出带宽“max_throughput_out”,参数用法与语义以下(默认为-1,表示不控制):
// Network throughput limit. // The network bandwidth is shared by all connections: // * busy connections get more bandwidth. // * the total bandwidth of all connections will not exceed the limit. int max_throughput_in; // max network in throughput for all connections. // in MB/s, should >= -1, -1 means no limit, default -1. int max_throughput_out; // max network out throughput for all connections. // in MB/s, should >= -1, -1 means no limit, default -1.
对于client端,若是限定了带宽流量,同时请求发送速度过快,来不及发出去的请求就会积压在Request Pending Buffer中。用户能够在Options指定该buffer的大小,若是buffer满了,请求就会当即返回RPC_ERROR_SEND_BUFFER_FULL的错误,用户能够根据须要进行处理,譬如减缓发送速度。在 RpcServerOptions 和 RpcClientOptions 中均可以指定“max_pending_buffer_size”:
int max_pending_buffer_size; // max size of pending buffer for one connection. // in MB, should >= 0, 0 means no buffer, default 2.
另外需注意:流量控制依据的是用户业务数据的数据量,不包含socket底层的包头协议数据的数据量,因此通常实际出入的数据量会比指定的略大。
如下是某实际系统中的网络流量监控图(带宽限制设置为15MB/s):
sofa-pbrpc提供日志打印函数SLOG(),将日志打印到标准错误输出,使用方式相似于printf()。
日志级别由高到低为:
经过打印级别控制日志输出,只会输出高于或者等于打印级别的日志,默认级别为ERROR。
用户可经过SOFA_PBRPC_SET_LOG_LEVEL()设置打印级别,譬如设置为INFO:
SOFA_PBRPC_SET_LOG_LEVEL(INFO);
日志使用样例:
SLOG(ERROR, "error message: %s", message);
RpcController用于控制单次请求的调用过程。
在Client端调用方法时,都须要传入一个RpcController,其做用是:
获取本地和远程的网络地址; 若是服务失败,设置失败标志和错误信息;
使用RpcController时需注意以下几点:
- RpcController用于控制单次请求的调用过程,每次RPC请求都须要建立一个RpcController,在本次请求完成前,其不得释放或者重用;
- 请求完成后,该RpcController可使用Reset()方法恢复初始状态以进行重用;
- RpcController的不一样接口有不一样的使用时间范围,只有在规定的时间范围内使用,接口才能返回正确结果,不然行为是不肯定的;
RPC请求失败时,RpcController的Failed()接口会返回true,同时错误信息能够从ErrorCode()和ErrorText()中得到。
错误的缘由主要有两大类:
参数名 | 参数说明 |
---|---|
work_thread_num | 工做线程数 |
max_pending_buffer_size | pengding buffer 大小 (MB) |
max_throughput_in | 最大入带宽限制 (MB/s) |
max_throughput_out | 最大出带宽限制 (MB/s) |
keep_alive_time | 空闲链接维持时间 (s) |
参数名 | 参数说明 |
---|---|
work_thread_num | 工做线程数 |
callback_thread_num | 回调线程数 |
max_pending_buffer_size | pengding buffer 大小 (MB) |
max_throughput_in | 最大入带宽限制 (MB/s) |
max_throughput_out | 最大出带宽限制 (MB/s) |
在建立RpcChannel时,能够指定多个功能对等的Server地址。在调用服务时,会根据负载均衡策略选择合适的Server发送请求,并自动进行容错和探活处理。
RpcChannel支持点对多点的构造函数:
RpcChannel(RpcClient* rpc_client, const std::vector<std::string>& address_list, const RpcChannelOptions& options = RpcChannelOptions()); // Create multiple server points by address provider. // The "rpc_client" is owned by the caller. // The "address_provider" is owned by the caller. RpcChannel(RpcClient* rpc_client, AddressProvider* address_provider, const RpcChannelOptions& options = RpcChannelOptions());
在上面第二个函数中,用户能够提供一个AddressProvider,支持动态增长或者删除server地址。
负载均衡策略:
容错与探活策略:
具体策略实现能够参考 src/sofa/pbrpc/dynamic_rpc_channel_impl.cc
使用样例代码能够参考 test/perf_test/client_multi_server.cc
AddressProvider的高级使用能够参考 sample/multi_server_sample
sofa-pbrpc提供了一些方便用户开发的工具类,包括:
类别 | 头文件 | 说明 |
---|---|---|
智能指针 | sofa/pbrpc/smart_ptr/smart_ptr.hpp | 包括scoped_ptr,shared_ptr,weak_ptr等 |
原子操做 | sofa/pbrpc/atomic.h | 支持fetch,inc,dec,cas等 |
锁操做 | sofa/pbrpc/locks.h | 提供了互斥锁,自旋锁,读写锁的封装 |
定时管理 | sofa/pbrpc/timeout_manager.h | 高效的提供了定时器功能 |
具体使用方法请直接参考头文件。
sofa-pbrpc提供了Mock测试支持,便于用户编写测试程序。
Mock功能的接口主要参考"sofa/pbrpc/mock_test_helper.h"文件,使用样例可参考"sample/mock_sample/"。
主要提供了五个宏:
// Enable or disable the mock feature. Default disabled. // The mock channel and mock methods will take effect iff mock enabled. #define SOFA_PBRPC_ENABLE_MOCK() ::sofa::pbrpc::enable_mock() #define SOFA_PBRPC_DISABLE_MOCK() ::sofa::pbrpc::disable_mock() // If you create a channel with address of SOFA_PBRPC_MOCK_CHANNEL_ADDRESS, then the channel is a mock // channel. The mock channel will not create real socket connection, but just uses mock methods. #define SOFA_PBRPC_MOCK_CHANNEL_ADDRESS "/mock/" // All mock method implements should use this function signature. typedef ExtClosure<void( ::google::protobuf::RpcController*, const ::google::protobuf::Message*, ::google::protobuf::Message*, ::google::protobuf::Closure*)> MockMethodHookFunction; // Register a mock method implement. If mock enabled, all channels will prefer to call mock // method first. If the corresponding mock method is not registered, then call the real method. // // "method_name" is the full name of the method to be mocked, should be a c-style string. // "mock_method" is the mock method hook function, should be type of "MockMethodHookFunction*". // // For example: // MockMethodHookFunction* mock_method = sofa::pbrpc::NewPermanentExtClosure(&MockEcho); // SOFA_PBRPC_REGISTER_MOCK_METHOD("sofa.pbrpc.test.EchoServer.Echo", mock_method); #define SOFA_PBRPC_REGISTER_MOCK_METHOD(method_name, mock_method) \ ::sofa::pbrpc::MockTestHelper::GlobalInstance()->RegisterMockMethod(method_name, (mock_method)) // Clear all registered mock methods. This will not delete the cleared hook functions, which // are take ownership by user. #define SOFA_PBRPC_CLEAR_MOCK_METHOD() \ ::sofa::pbrpc::MockTestHelper::GlobalInstance()->ClearMockMethod()#
sofa-pbrpc提供了一个客户端工具sofa-pbrpc-client(位于"bin/"),用于查询server状态、获取服务列表及proto描述、获取服务调用统计、构建文本快速发送rpc请求等。
具体功能:
Usage: sofa-pbrpc-client <server-address> <sub-command> [args] Available subcommands: * help : print this usage help. * health :check if the server is healthy. * status :get status of the server. * option : get RpcServerOptions of the server. * list : list all services provided by the server. * desc <protobuf-type-name> :get descriptor of a protobuf type (service/message/enum). * call <method-full-name> <request-message-text> [timeout-in-ms] : call a method using the text format of request message.The "timeout-in-ms" is optional, default is 3000 milli-seconds. * stat [service-full-name] [period-in-seconds] : get the service statistics in the latest period of seconds.The "service-full-name" is optional, default is "all".The "period-in-seconds" is optional, default is 60 seconds.
使用注意:
- health、status、option、stat命令要求server端配置知足:disable_builtin_service = false;
- list、desc、call命令要求server端配置知足:disable_builtin_service = false && disable_list_service = false;
- 使用"call"命令发起rpc调用时,用户须要按照protobuf的text格式构造Request数据,其使用google.protobuf.TextFormat进行序列化和反序列化。返回的Response数据也使用text格式打印出来。实际上,text格式也就是message->DebugString()打印出来的格式。若是字符串中包含回车,在做为命令行参数时建议使用单引号括起来。实现上,sofa-pbrpc-client首先获取Server端服务的描述信息,而后经过反射的方式构建请求数据,发送rpc请求。这个功能对调试颇有帮助,另外这个思路也能够用来实现http代理。
使用样例: 向监听地址为127.0.0.1:12321的server发送rpc调用"sofa.pbrpc.test.EchoServer.Echo"
$ ./sofa-pbrpc-client 127.0.0.1:12321 call sofa.pbrpc.test.EchoServer.Echo \ 'message:"hello from qinzuoyan01"' Response: ------------------------------ message: "echo message: hello from qinzuoyan01" ------------------------------
sofa-pbrpc支持对服务的调用进行统计,并之内建服务的方式导出统计信息。内建服务的proto定义参见"sofa/pbrpc/builtin_service.proto"。
包含以下统计项:
$ ./sofa-pbrpc-client 127.0.0.1:12321 stat sofa.pbrpc.test.EchoServer 10
上述命令用于获取"sofa.pbrpc.test.EchoServer.Echo"在最近10秒的调用统计,结果样例以下:
Response: ------------------------------ service_stats { service_name: "sofa.pbrpc.test.EchoServer" period_seconds: 10 succeed_count: 1151699 failed_count: 0 method_stats { method_name: "sofa.pbrpc.test.EchoServer.Echo" succeed_count: 1151699 succeed_avg_time_us: 0.98021704 succeed_max_time_us: 1108 failed_count: 0 failed_avg_time_us: 0 failed_max_time_us: 0 } } ------------------------------
除此以外,内建服务还提供了一些监控server状态的接口。sofa-pbrpc-client工具也提供了这些子命令:
sofa-pbrpc从1.0.1开始支持HTTP方式调用服务,同时支持原生POST,GET以及扩展的POST PROTOBUF三种方式提交。另外还提供了Web监控页面,方便开发和测试。
样例能够参见sample/echo/client_http.sh。
curl -d '{"message":"Hello, world!"}' http://localhost:12321/sofa.pbrpc.test.EchoServer.Echo
规则:
curl http://localhost:12321/sofa.pbrpc.test.EchoServer.Echo?request=%7B%22message%22%3A%22Hello%2C%20world%21%22%7D
规则:
普通的GET POST请求使用JSON传递数据,在字段增多的状况下性能降低严重。 因此在条件许可的状况下请使用HTTP POST PROTOBUF的接口,样例能够参见:python/sample/client_http_protobuf.py
提供的页面(假设server监听端口为8080):
主页示例