srpc: four RPC protocols on Sogou Workflow
RPC framework based on C++ Workflow. Supports SRPC, Baidu bRPC, Tencent tRPC, thrift protocols.
At a glance
- What is it?
- srpc gives a C++ service one implementation that answers SRPC, Baidu bRPC, Tencent tRPC and Thrift traffic on top of Sogou Workflow. It fits teams already inside that ecosystem, and it does not fit a stack that needs one RPC layer across several languages.
- Who is it for?
- Adopt srpc when the service is C++, already sits on Sogou Workflow, and has to answer Baidu bRPC or Tencent tRPC callers it cannot change. Skip it when the RPC layer must span languages beyond the HTTP+JSON port, because that endpoint is a translation over a Protobuf interface, not a first class SDK.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 38 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 18, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why Sogou built srpc on top of Workflow
Almost every online service at Sogou speaks RPC, and the company did not settle on one wire format. It built SRPC, a C++ framework layered on Sogou C++ Workflow that answers four protocol families from a single service implementation: its own SRPC, Baidu bRPC, Tencent tRPC and Thrift. Sogou says almost all of its online services run on that system, handling tens of billions of requests a day across search, recommendation and advertising, which is deployment context rather than a published capacity figure.
The multi-protocol surface is the reason to look at it. A handler written against `Example::Service` is served as SRPC, bRPC, tRPC and Thrift, so callers do not have to match the server's dialect, and `Json`, `Protobuf` and `Thrift Binary` payloads travel the same routes.
Cross-cutting concerns sit in aspects instead of inside your handler. Those aspects report tracing to OpenTelemetry and metrics to OpenTelemetry or `Prometheus`, while the process keeps Workflow's name service and upstream components. A team already running Workflow gets discovery and observability without adding a second runtime. What the README does not say is how Sogou's services divide between those four protocols, so the ratio between SRPC and bRPC traffic stays unknown.
protoc plus srpc_generator produce the service header
The build has two steps before any C++ exists. Write the interface as a Protobuf file, run `protoc` for the message classes, then run `srpc_generator` for the service glue:
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);
};The proto2 note is not decoration, though. The sample sets proto3 syntax, and srpc reads either dialect, so an existing Protobuf schema does not have to be rewritten to move a service onto this framework.
protoc example.proto --cpp_out=./ --proto_path=./
srpc_generator protobuf ./example.proto ./`protoc` writes `example.pb.cc` next to the .proto file. `srpc_generator` takes the same file and produces the service header that the server and the client both include as `example.srpc.h`. One detail the walkthrough leaves open: neither g++ line later on names a source file from `srpc_generator`, only `example.pb.cc`, so whatever the generator emits beyond that header is not visible from the README alone. Inside the tutorial directory the interface is repeated per protocol, with separate server files for SRPC, bRPC, Thrift and tRPC.
One handler object behind port 1412 and port 8811
One service object is registered twice, and that is the whole arrangement. `ExampleServiceImpl` is added to an `SRPCServer` and to an `SRPCHttpServer`, each listening on its own port inside the same process:
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);The native listener takes 1412 and the HTTP listener takes 8811, exposing the same method at a path assembled from the names in the .proto file: service Example, method Echo. That is the cheapest interoperability route in the project, since a caller in another language gets JSON over HTTP while the process keeps its binary protocol for everyone else.
Both front doors share the handler's memory, and shutdown is two stop calls issued together. The walkthrough keeps the process alive with `getchar()`, so pressing Enter in the server terminal is what ends it. A long-running deployment replaces that with real lifecycle handling, which the README does not describe.
The client callback carries status, error and message
The client receives no return value. It hands a lambda to the call and moves on:
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());
});`RPCContext` carries the verdict and the detail behind it, and its four accessors do not overlap. `success()` answers the yes or no question, `get_status_code()` gives a protocol level code, `get_error()` a transport error, `get_errmsg()` the message text. The sample prints the response body on success and all three failure fields on failure, which is the minimum a caller needs to tell a rejected request from a broken connection.
Address and port are constructor arguments, so a client is bound to one endpoint rather than to a discovery name. The example shows no name service lookup even though Workflow provides one, and it never names a protocol, because framing, serialisation and transport all sit below the callback.
Linux g++ lines against a library already installed
srpc is packaged for Debian and Fedora, so there are two routes: a system package or a source build. The walkthrough takes the second one, and it is terse:
g++ -o server server.cc example.pb.cc -std=c++11 -lsrpc
g++ -o client client.cc example.pb.cc -std=c++11 -lsrpcBoth lines link the installed srpc shared library and set C++11 as the language floor. That ordering matters for a first timer, since the quick start assumes srpc is already on the system and is not a from-scratch build. Neither the package name for Debian and Fedora nor the include path for the generated header appears in the walkthrough; the README points at `docs/en/installation.md` for Linux, MacOS and Windows instead.
Supported platforms run wider than those two lines show, and the README admits the limit. The compile commands are for Linux only, and the tutorial directory carries a complete cmake project for everything else. The repository root keeps both build systems in plain sight: `CMakeLists.txt`, `CMakeLists_Headers.txt`, `srpc-config.cmake.in` and `GNUmakefile` for cmake, then `BUILD`, `WORKSPACE`, `srpc.bzl` and `.bazelignore` for Bazel.
Compression and transport resolved below the service layer
Transport and payload decisions happen underneath the service class, which is why the handler above never mentions them. Four compression algorithms are unpacked by the framework instead of by your code: `gzip`, `zlib`, `snappy` and `lz4`. Four transports are available transparently, tcp, udp, sctp and tcp ssl. Nothing in the example selects any of them, because the choice belongs to configuration the walkthrough does not print.
Payload shape is equally loose. `Json`, `Protobuf` and `Thrift Binary` travel the same routes, and the HTTP listener turns a method into a JSON endpoint. That endpoint is what makes srpc reachable from a language with no SRPC client at all:
curl 127.0.0.1:8811/Example/Echo -H 'Content-Type: application/json' -d '{message:"from curl",name:"CURL"}'That reply body is `{"message":"Hi, CURL"}`, and the server terminal prints the same call arriving over the binary port. One process, two wire formats, no adapter code in between. The trade is that the HTTP route is a translation over a Protobuf interface: those field names are the field names in `example.proto`, so a schema change reaches both doors and cannot be made on one side alone.
The benchmark drives bRPC traffic from a foreign client
Only one place in the README carries numbers, and reading it closely pays off. The load driver is named first: BAIDU brpc-client in pooled connection pool mode. The published QPS therefore measures srpc answering Baidu bRPC traffic, not srpc talking to its own client, which makes it interoperability evidence rather than an end to end speed figure.
Conditions there are stated precisely. A single client process varies its threads across 64, 128, 256, 512 and 1024 against one server running 16 I/O threads and 16 handler threads, with a 32 byte request and 20s per run. The second chart holds each client at 32 threads and scales client processes from 1 to 16 instead. Hardware is one machine, 128G of memory and 10 Gigabit Ethernet.
Two things do not line up there. The hardware line names an Intel Xeon E5-2630 v3 at 2.40GHz as 2-chip/8-core/32-processor, and the same line calls that part 8-core, so the processor count and the named CPU disagree. The server configuration then places 32 threads on those 8 cores. Both results are images under `docs/images/`, so no QPS number appears in text at all. A reader who wants the figures has to open `benchmark2.png` and the second chart, and the top level `benchmark/` directory holds the harness.
Two documentation trees and no upgrade notes
Documentation for an English reader is split across two path styles, which is easy to trip over. The installation guide and the feature list live under `docs/en/`, while the pages for Workflow, HTTP+JSON, tracing and metrics are linked as `docs/docs-06-workflow.md`, `docs/docs-07-srpc-http.md`, `docs/docs-08-tracing.md` and `docs/docs-09-metrics.md`. The root also carries `README_cn.md` as the Chinese entry, so an English reader opens the English README and then follows links into two different document trees.
The rest of the tree shows where the work sits. `src/` holds the framework, `test/` and `benchmark/` the harnesses, `docs/` the guides, `tutorial/` the per protocol examples, `tools/` a helper described as a way to build Workflow and SRPC projects easily, and `workflow` the upstream dependency, listed next to `.gitmodules` and `third_party/`.
What is missing is as informative as what is there. Apache-2.0 covers the repository and the last push was on 2026-09-15, yet the README describes no version pinning policy, no upgrade path from an older srpc and no compatibility matrix between the bRPC, tRPC and Thrift implementations it carries. `docs/en/rpc.md` and the tutorial directory are the places to check before pinning a dependency.
Editorial conclusion
Adopt srpc when the service is C++, already sits on Sogou Workflow, and has to answer Baidu bRPC or Tencent tRPC callers it cannot change. Skip it when the RPC layer must span languages beyond the HTTP+JSON port, because that endpoint is a translation over a Protobuf interface, not a first class SDK. Before pinning it, build one tutorial example on your own platform, since the g++ lines are Linux only, they link an already installed srpc, and no package name is given for the Debian and Fedora builds.
Frequently asked questions
What is srpc and which RPC protocols does it support?
srpc is Sogou's C++ RPC framework built on Sogou C++ Workflow. A single service implementation answers SRPC, Baidu bRPC, Tencent tRPC and Thrift, and the interface can be written in Protobuf or Thrift IDL.
How do I install srpc on Debian or Fedora?
The project is packaged for Debian and Fedora, so it can come from a system package or a source build, with the Linux, MacOS and Windows guide at docs/en/installation.md. The quick start compiles with g++ and links -lsrpc, so the library has to be on the system before those two lines work.
Can a client in another language call an srpc server?
Yes, through the HTTP+JSON listener. The quick start registers one service on both port 1412 and port 8811, and the curl example posts JSON to /Example/Echo and reads back {"message":"Hi, CURL"}.
Does srpc report metrics and traces?
Yes. Aspect oriented modules report tracing to OpenTelemetry and metrics to OpenTelemetry and Prometheus, with guides at docs/docs-08-tracing.md and docs/docs-09-metrics.md.
What QPS does srpc reach?
The README publishes no QPS figure in text. It fixes the conditions instead: one machine with an Intel Xeon E5-2630 v3 at 2.40GHz, 128G of memory and 10 Gigabit Ethernet, a 32 byte request and 20s runs, with the Baidu bRPC client in pooled mode as the load driver, and the results are images.
Does srpc support both proto2 and proto3?
Yes. The example .proto comment states that both are supported, and the sample file itself uses syntax = "proto3".
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sogou-srpc)