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):
主頁示例