V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
holmes1412
V2EX  ›  C++

自荐一个企业级的轻量 RPC

  •  2
     
  •   holmes1412 · 2022-02-18 18:05:09 +08:00 · 4064 次点击
    这是一个创建于 1007 天前的主题,其中的信息可能已经有所发展或是发生改变。

    SRPC 是全搜狗以及腾讯部分业务线上使用的 RPC 框架,包括多种 IDL(protobuf/thrift)、多种 RPC 协议( srpc/brpc/thrift/tRPC ,且 tRPC 协议是唯一授权的开源版实现)、二进制协议与 HTTP 互转、支持多种压缩算法,AOP 模块化方式支持框架级数据上报(可对接 OpenTelemetry )。

    以上这些层次都在同一套代码里,用了多种多态的方式互通每层的不同类功能,架构整体是解耦合的,因此代码很短只有一万多行。接口上用了代码生成,rpc 接口比 protobuf 原生简单,且 thrift 纯自解析、接口与原生兼容。轻量级的体现除了代码精简以外,还有依赖少、编译快(单核编译 32 秒)、体积小( strip -S 后 1.4M )、内存小(示例 server 跑起来 4M )。

    目前每天上百亿的请求量,涵盖搜广推业务,稳定且性能好。虽然企业级的应用几十万 QPS 也是基操,但更重要的还是高 QPS 下保证请求延迟的稳定性。另外支持 Windows ,发现使用者中用 Windows 的占比还不小。

    Proto 文件:

    syntax = "proto3"; // both proto2 and proto3 are supported
    
    message EchoRequest {
        string message = 1;
        string name = 2;
    };
    
    message EchoResponse {
        string message = 1;
    };
    
    service Example {
        rpc Echo(EchoRequest) returns (EchoResponse);
    };
    

    Server 实现:

    #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());
        }
    };
    
    int main()
    {
        SRPCServer server_tcp;
        SRPCHttpServer server_http; // 同时启动一个 http server
    
        ExampleServiceImpl impl;
        server_tcp.add_service(&impl); // 同一份实现可以加到多种协议的 server 中
        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;
    }
    

    Client 调用:

    #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("v2ex");
    
        client.Echo(&req, [](EchoResponse *response, RPCContext *ctx) {
        	if (ctx->success())
                printf("%s\n", response->DebugString().c_str());
        });
    
        getchar(); // press "Enter" to end.
        return 0;
    }
    

    也可以用 curl 直接发 http 请求到 http server 中:

    curl 127.0.0.1:8811/Example/Echo -H 'Content-Type: application/json' -d '{message:"Hello, srpc!",name:"CURL"}'
    

    由于 SRPC 定位很轻量级,目前我们也在继续往周边生态探索和建设中。项目主页有 benchmark 、wiki 以及 tutorial 现成示例,欢迎大家提出宝贵的建议。

    项目地址: https://github.com/sogou/srpc

    14 条回复    2022-02-25 23:01:13 +08:00
    uurun
        1
    uurun  
       2022-02-18 18:21:26 +08:00
    nice
    guyeu
        2
    guyeu  
       2022-02-18 21:01:22 +08:00
    跨语言哇,至少跨 go 、java 、python 哇
    holmes1412
        3
    holmes1412  
    OP
       2022-02-18 21:14:36 +08:00
    @guyeu 跨的!用 http 协议打通了 srpc/thrift/trpc 的二进制协议就是干这个的,所以其他语言只要用 http 就可以互通~上边的示例是用 curl 发,文档里也有 python 发 http 的例子(>_<)~
    holmes1412
        4
    holmes1412  
    OP
       2022-02-18 21:30:48 +08:00
    @guyeu 但是如果说二进制协议的跨语言是没有的,只有 C++实现。其他语言互通可以考虑用 http 的传输,因为 http 或二进制传输,对业务开发完全透明。
    pursuer
        5
    pursuer  
       2022-02-18 23:03:00 +08:00
    我前段时间也整了个 RPC 来着
    https://github.com/Pursuer2/PxpRpc
    真实极简,到目前 IDL 都还没有,就给客户端做了个方法签名...
    主要目的是不同语言 /平台交互用的
    谁还能更轻量?(
    wzzzx
        6
    wzzzx  
       2022-02-18 23:13:26 +08:00
    这阵子接手的项目,有个大佬就在里面自己写了一套 RPC 服务,代码真实短小精干,不过千行的代码。不过利用 Qt 的反射能力,可能没法照搬给别的语言
    3dwelcome
        7
    3dwelcome  
       2022-02-18 23:16:22 +08:00 via Android
    我也自己弄了一套二进制 RPC 。
    前端复杂后,光 restful 完全不够用了。
    开始面向 RPC 编程。
    lesismal
        8
    lesismal  
       2022-02-19 00:07:29 +08:00
    早就 star 过了,代码很赞。

    但我最关心的问题是:holmes1412/liyingxin 真是个妹子吗?如果是妹子,那请先收下我的膝盖
    cpprookie
        9
    cpprookie  
       2022-02-19 15:41:17 +08:00
    非常 nice 的框架
    holmes1412
        10
    holmes1412  
    OP
       2022-02-20 19:25:05 +08:00 via iPhone
    @lesismal 不收不收!只是一只普通的工程师!
    另外感谢认可,代码还可以写得更好一点~~
    guyeu
        11
    guyeu  
       2022-02-21 11:18:22 +08:00
    @holmes1412 如果要用 c++的客户端调 python 的服务端呢?
    holmes1412
        12
    holmes1412  
    OP
       2022-02-21 11:35:05 +08:00
    @guyeu 那么就先用 python 起一个 http server ,然后用 SRPCHttpClient ,就可以 client.Echo(req, ...) 这样使用 srpc 框架发送~
    mirage13
        13
    mirage13  
       2022-02-24 08:33:09 +08:00
    @wzzzx 可以开源学习下吗?
    wzzzx
        14
    wzzzx  
       2022-02-25 23:01:13 +08:00
    @mirage13 #13 不好意思,是公司的项目里的代码,没法开源
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1077 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 22:46 · PVG 06:46 · LAX 14:46 · JFK 17:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.