SRPC

License Language Platform

Introduction

这是搜狗自研的RPC系统,主要功能和特点:

  • 这是一个基于Sogou C++ Workflow的项目,兼具:
    • 高性能
    • 低开发和接入门槛
    • 完美兼容workflow的串并联任务流
    • 对于已有pb/thrift描述文件的项目,可以做到一键迁移
  • 支持多种IDL格式,包括:
    • Protobuf
    • Thrift
  • 支持多种数据布局,使用上完全透明,包括:
    • Protobuffer serialize
    • Thrift Binary serialize
    • json serialize
  • 支持多种压缩,使用上完全透明,包括:
    • gzip
    • zlib
    • snappy
    • lz4
  • 支持多种通信协议,使用上完全透明,包括:
    • tcp
    • http
    • sctp
    • ssl
    • https
  • 用户可以通过http+json实现跨语言:
    • 如果自己是server提供方,用任何语言的http server接受post请求,解析若干http header即可
    • 如果自己是client调用方,用任何语言的http client发送post请求,添加若干http header即可
  • 内置了可以与其他RPC框架的server/client无缝互通的client/server,包括:
    • BPRC
    • GRPC
    • Thrift Framed Binary
    • Thrift Http Binary
  • 兼容workflow的使用方式:
    • 提供创建任务的接口来创建一个rpc任务
    • 可以把rpc任务放到任务流图中,回调函数里也可以拿到当前的任务流
    • workflow所支持的其他功能,包括upstream、计算调度、异步文件IO等
  • 更多功能和层次介绍

Installation

  • srpc是一个静态库libsrpc.a,只有开发环境需要依赖libsrpc,编译后二进制发布不需要依赖libsrpc库
  • srpc依赖workflow和protobuf3
    • protobuf需要用户自行安装v3.0.0以上的版本
      • workflow可以通过git的submodule形式进行依赖
      • 压缩库snappy和lz4也以submodule的形式在third_party/中作源码依赖
  1. git clone --recursive https://github.com/sogou/srpc.git
  2. cd srpc
  3. make
  4. sudo make install

Quick Start

1. example.proto

  1. syntax = "proto2";//这里proto2和proto3都可以,srpc都支持
  2. message EchoRequest {
  3. optional string message = 1;
  4. optional string name = 2;
  5. };
  6. message EchoResponse {
  7. optional string message = 1;
  8. };
  9. service Example {
  10. rpc Echo(EchoRequest) returns (EchoResponse);
  11. };

2. generate code

  1. protoc example.proto --cpp_out=./ --proto_path=./
  2. srpc_generator protobuf ./example.proto ./

3. server.cc

  1. #include <stdio.h>
  2. #include <signal.h>
  3. #include "example.srpc.h"
  4. using namespace srpc;
  5. class ExampleServiceImpl : public Example::Service
  6. {
  7. public:
  8. void Echo(EchoRequest *request, EchoResponse *response, RPCContext *ctx) override
  9. {
  10. response->set_message("Hi, " + request->name());
  11. // gzip/zlib/snappy/lz4/none
  12. // ctx->set_compress_type(RPCCompressGzip);
  13. // protobuf/json
  14. // ctx->set_data_type(RPCDataJson);
  15. printf("get_req:\n%s\nset_resp:\n%s\n",
  16. request->DebugString().c_str(), response->DebugString().c_str());
  17. }
  18. };
  19. void sig_handler(int signo) { }
  20. int main()
  21. {
  22. signal(SIGINT, sig_handler);
  23. signal(SIGTERM, sig_handler);
  24. SRPCServer server_tcp;
  25. SRPCHttpServer server_http;
  26. ExampleServiceImpl impl;
  27. server_tcp.add_service(&impl);
  28. server_http.add_service(&impl);
  29. server_tcp.start(1412);
  30. server_http.start(8811);
  31. pause();
  32. server_http.stop();
  33. server_tcp.stop();
  34. return 0;
  35. }

4. client.cc

  1. #include <stdio.h>
  2. #include "example.srpc.h"
  3. using namespace srpc;
  4. int main()
  5. {
  6. Example::SRPCClient client("127.0.0.1", 1412);
  7. EchoRequest req;
  8. req.set_message("Hello, srpc!");
  9. req.set_name("workflow");
  10. client.Echo(&req, [](EchoResponse *response, RPCContext *ctx) {
  11. if (ctx->success())
  12. printf("%s\n", response->DebugString().c_str());
  13. else
  14. printf("status[%d] error[%d] errmsg:%s\n",
  15. ctx->get_status_code(), ctx->get_error(), ctx->get_errmsg());
  16. });
  17. pause();
  18. return 0;
  19. }

5. make

  1. g++ -o server server.cc example.pb.cc -std=c++11 -lsrpc
  2. g++ -o client client.cc example.pb.cc -std=c++11 -lsrpc

6. run

终端1

  1. ./server

终端2

  1. ./client
  2. curl 127.0.0.1:8811/Example/Echo -H 'Content-Type: application/json' -d '{message:"from curl",name:"CURL"}'

终端1输出

  1. get_req:
  2. message: "Hello, srpc!"
  3. name: "workflow"
  4. set_resp:
  5. message: "Hi, workflow"
  6. get_req:
  7. message: "from curl"
  8. name: "CURL"
  9. set_resp:
  10. message: "Hi, CURL"

终端2输出

  1. message: "Hi, workflow"
  2. {"message":"Hi, CURL"}

Tutorial

Benchmark

  • CPU 2-chip/8-core/32-processor Intel(R) Xeon(R) CPU E5-2630 v3 @2.40GHz
  • Memory all 128G
  • 10 Gigabit Ethernet
  • BAIDU brpc-client使用连接池pooled模式

跨机单client→单server在不同并发的QPS

  1. Client = 1
  2. ClientThread = 64, 128, 256, 512, 1024
  3. RequestSize = 32
  4. Duration = 20s
  5. Server = 1
  6. ServerIOThread = 16
  7. ServerHandlerThread = 16

IMG

跨机多client→单server在不同client进程数的QPS

  1. Client = 1, 2, 4, 8, 16
  2. ClientThread = 32
  3. RequestSize = 32
  4. Duration = 20s
  5. Server = 1
  6. ServerIOThread = 16
  7. ServerHandlerThread = 16

IMG

同机单client→单server在不同并发下的QPS

  1. Client = 1
  2. ClientThread = 1, 2, 4, 8, 16, 32, 64, 128, 256
  3. RequestSize = 1024
  4. Duration = 20s
  5. Server = 1
  6. ServerIOThread = 16
  7. ServerHandlerThread = 16

IMG

同机单client→单server在不同请求大小下的QPS

  1. Client = 1
  2. ClientThread = 100
  3. RequestSize = 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
  4. Duration = 20s
  5. Server = 1
  6. ServerIOThread = 16
  7. ServerHandlerThread = 16

IMG

同机单client→单server在固定QPS下的延时CDF

  1. Client = 1
  2. ClientThread = 50
  3. ClientQPS = 10000
  4. RequestSize = 1024
  5. Duration = 20s
  6. Server = 1
  7. ServerIOThread = 16
  8. ServerHandlerThread = 16
  9. Outiler = 1%

IMG

跨机多client→单server在固定QPS下的延时CDF

  1. Client = 32
  2. ClientThread = 16
  3. ClientQPS = 2500
  4. RequestSize = 512
  5. Duration = 20s
  6. Server = 1
  7. ServerIOThread = 16
  8. ServerHandlerThread = 16
  9. Outiler = 1%

IMG

Authors