SPRC is an enterprise-level RPC system used by almost all online services in Sogou. It handles tens of billions of requests every day, covering searches, recommendations, advertising system, and other types of services. Its main features include:
- Base on Sogou C++ Workflow, with the following features:
- High performance, low latency, lightweight
- Low development and access cost
- Compatible with SeriesWork and ParallelWork in Workflow
- One-click migration for existing projects with protobuf/thrift
- Supports multiple operating systems: Linux / MacOS / Windows
- Support several IDL formats, including:
- Protobuf
- Thrift
- Support several data formats, including:
- Protobuf serialize
- Thrift Binary serialize
- JSON serialize
- Support several compression formats transparently, including:
- gzip
- zlib
- snappy
- lz4
- Support several communication protocols transparently, including:
- tcp
- http
- sctp
- ssl
- https
- With HTTP+JSON, you can use any language:
- As a server, you can accept POST requests with HTTP server developed in any language and parse the HTTP headers.
- As a client, you can send POST requests with HTTP client developed in any language and add the required HTTP headers.
- Built-in client/server which can seamlessly communicate with a server/client in other RPC frameworks, including:
- SRPC
- BRPC
- TRPC (the only open-source implementation of TRPC protocol so far)
- Thrift Framed Binary
- Thrift Http Binary
- How to use it together with Workflow:
- You can use the interface to create an RPC task
- You can put the RPC task into SeriesWork or ParallelWork, and you can also get the current SeriesWork in the callback.
- You can also use other features supported by Workflow, including upstream, calculation scheduling, asynchronous file IO, etc.
- AOP Modular Plugin Management:
- Able to connect to OpenTelemetry (report Tracing)
- Easy to report to other Cloud Native systems
- srpc Envoy-filter for the users of Kubernetes
- More features and layers
- srpc is a static library, libsrpc.a. You only need to add the libsrpc as a dependency in the development environment, and it is not required in the compiled binary release.
- srpc depends on Workflow and protobuf3.
- For protobuf, you must install protobuf v3.12.0 or above by yourself.
- For Workflow, it`s added as dependency automatically via git submodule.
- For snappy and lz4, source codes are also included as third_party via git submodule.
- Workflow, snappy and lz4 can also be found via installed package in the system. If the submodule dependencies are not pulled in thirt_party, they will be searched from the default installation path of the system. The version of snappy is required v1.1.6 or above.
- There is no difference in the srpc code under the Windows version, but users need to use the windows branch of Workflow
git clone --recursive https://github.com/sogou/srpc.git
cd srpc
make
- Step 1: Design IDL description file
- Step 2: Implement ServiceIMPL
- Step 3: Start the Server
- Step 4: Use the Client
- Step 5: Understand asynchrous Context
- Step 6: Use it together with the Workflow
- Step 7: Common Usage of HTTP
- Step 8: Report Tracing to OpenTelemetry
Easy to compile tutorial with these commands:
cd tutorial
make
syntax = "proto3";// You can use either proto2 or proto3. Both are supported by srpc
message EchoRequest {
string message = 1;
string name = 2;
};
message EchoResponse {
string message = 1;
};
service Example {
rpc Echo(EchoRequest) returns (EchoResponse);
};
protoc example.proto --cpp_out=./ --proto_path=./
srpc_generator protobuf ./example.proto ./
#include <stdio.h>
#include <signal.h>
#include "example.srpc.h"
using namespace srpc;
class ExampleServiceImpl : public Example::Service
{
public:
void Echo(EchoRequest *request, EchoResponse *response, RPCContext *ctx) override
{
response->set_message("Hi, " + request->name());
printf("get_req:\n%s\nset_resp:\n%s\n",
request->DebugString().c_str(), response->DebugString().c_str());
}
};
void sig_handler(int signo) { }
int main()
{
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
SRPCServer server_tcp;
SRPCHttpServer server_http;
ExampleServiceImpl impl;
server_tcp.add_service(&impl);
server_http.add_service(&impl);
server_tcp.start(1412);
server_http.start(8811);
getchar(); // press "Enter" to end.
server_http.stop();
server_tcp.stop();
return 0;
}
#include <stdio.h>
#include "example.srpc.h"
using namespace srpc;
int main()
{
Example::SRPCClient client("127.0.0.1", 1412);
EchoRequest req;
req.set_message("Hello, srpc!");
req.set_name("workflow");
client.Echo(&req, [](EchoResponse *response, RPCContext *ctx) {
if (ctx->success())
printf("%s\n", response->DebugString().c_str());
else
printf("status[%d] error[%d] errmsg:%s\n",
ctx->get_status_code(), ctx->get_error(), ctx->get_errmsg());
});
getchar(); // press "Enter" to end.
return 0;
}
These compile commands are only for Linux system. On other system, complete cmake in tutorial is recommanded.
g++ -o server server.cc example.pb.cc -std=c++11 -lsrpc
g++ -o client client.cc example.pb.cc -std=c++11 -lsrpc
Terminal 1:
./server
Terminal 2:
./client
We can also use CURL to post Http request:
curl 127.0.0.1:8811/Example/Echo -H 'Content-Type: application/json' -d '{message:"from curl",name:"CURL"}'
Output of Terminal 1:
get_req:
message: "Hello, srpc!"
name: "workflow"
set_resp:
message: "Hi, workflow"
get_req:
message: "from curl"
name: "CURL"
set_resp:
message: "Hi, CURL"
Output of Terminal 2:
message: "Hi, workflow"
Output of CURL:
{"message":"Hi, CURL"}
- 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 in pooled (connection pool) mode
Client = 1
ClientThread = 64, 128, 256, 512, 1024
RequestSize = 32
Duration = 20s
Server = 1
ServerIOThread = 16
ServerHandlerThread = 16
Client = 1, 2, 4, 8, 16
ClientThread = 32
RequestSize = 32
Duration = 20s
Server = 1
ServerIOThread = 16
ServerHandlerThread = 16
Client = 1
ClientThread = 1, 2, 4, 8, 16, 32, 64, 128, 256
RequestSize = 1024
Duration = 20s
Server = 1
ServerIOThread = 16
ServerHandlerThread = 16
Client = 1
ClientThread = 100
RequestSize = 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
Duration = 20s
Server = 1
ServerIOThread = 16
ServerHandlerThread = 16
Client = 1
ClientThread = 50
ClientQPS = 10000
RequestSize = 1024
Duration = 20s
Server = 1
ServerIOThread = 16
ServerHandlerThread = 16
Outiler = 1%
Client = 32
ClientThread = 16
ClientQPS = 2500
RequestSize = 512
Duration = 20s
Server = 1
ServerIOThread = 16
ServerHandlerThread = 16
Outiler = 1%
- Email - liyingxin@sogou-inc.com - main author
- Issue - You are very welcome to post questions to issues list.
- QQ - Group number:
618773193