查看: 97|回复: 10

开箱即用的C++高性能异步RPC框架 -- TinyRPC

[复制链接]

4

主题

9

帖子

17

积分

新手上路

Rank: 1

积分
17
发表于 2022-12-21 17:31:05 | 显示全部楼层 |阅读模式
1. 概述

各位好,我是 ikerli。这篇文章不是介绍原理,希望学习设计原理的同学们可以关注专栏的往期文章,后续也会持续输出:
老规矩还是先打个广告,TinyRPC 是一款由 c++11 开发的高性能的异步 RPC 框架,它的特点如下:

  • 高性能:HTTP echo 测试有 14w+ 的 QPS
  • 异步化:RPC 调用实现了真正的异步,且调用非常简单。底层通过协程将同步的代码实现出异步的性能
  • 。。。
目前由本人维护在 GitHub 上,项目地址为:
https://github.com/Gooddbird/tinyrpc
没点 star 的同学们帮忙动下小手,爱你哟  


看过之前的文章的同学都知道,即使 TinyRPC 已经封装得很好了,但是要使用起来还是略显繁琐,要自己写配置文件、自己注册 Service、 要用 protoc 生成 pb 文件、要继承并且实现 Service 等。这些步骤必不可少,却又显得有些繁琐。
甚至有一些同学安装好 TinyRPC 之后,完全不知道怎么使用,不知道如何使用此框架从零搭建一个RPC 服务。作为开发者,这锅我先背了。
最近 TinyRPC v1.2.0 的代码已经正式发布,是的,都是我拿命肝的。。这个版本最重要的特性就是代码生成器(tinyrpc_generator),而它的作用很明显: 开箱即用,非常轻松的就能搭建 RPC 服务了。话不多说,让我们看下如何使用吧:
2. TinyRPC Generator

Generator(生成器)用来生成 TinyRPC 项目,其代码位于 tinyrpc/generator/tinyrpc_generator.py 下面,其用python脚本实现。
利用 Generator,你仅仅需要一个 protobuf 文件即可一键创建  RPC 服务,接下来用一个实例来说明如何使用:
例如我们需要搭建一个订单RPC服务: order_server. 它的提供一些简单的订单操作方法:

  • 查询订单(query_order_detail)
  • 生成订单(make_order)
  • 删除订单(delete_order)
2.1 提供 Protobuf 文件

这一步很简单,按照自己的业务需求定制接口字段即可。例如 order_server.proto 文件如下:
syntax = "proto3";
option cc_generic_services = true;

message queryOrderDetailReq {
  int32 req_no = 1;         // 请求标识,一般是唯一id
  string order_id = 2;      // 单号
}

message queryOrderDetailRsp {
  int32 ret_code = 1;     // 返回码,0代表响应成功
  string res_info = 2;    // 返回信息, SUCC 代表成功,否则为失败的具体信息
  int32 req_no = 3;
  string order_id = 4;      // 单号
  string goods_name = 5;    // 货物名称
  string user_name = 6;     // 用户名称
}

message makeOrderReq {
  int32 req_no = 1;
  string user = 2;
  string goods_name = 3;    // 货物名称
  string pay_amount = 4;    // 支付金额
}

message makeOrderRsp {
  int32 ret_code = 1;
  string res_info = 2;
  int32 req_no = 3;
  string order_id = 4;      // 订单号
}

message deleteOrderReq {
  int32 req_no = 1;         // 请求标识,一般是唯一id
  string order_id = 2;      // 单号
}

message deleteOrderRsp {
  int32 ret_code = 1;
  string res_info = 2;
  int32 req_no = 3;
  string order_id = 4;      // 订单号
}


service OrderService {
  // 查询订单
  rpc query_order_detail(queryOrderDetailReq) returns (queryOrderDetailRsp);

  // 生成订单
  rpc make_order(makeOrderReq) returns (makeOrderRsp);

  // 删除订单
  rpc delete_order(deleteOrderReq) returns (deleteOrderRsp);

}2.2 生成 TinyRPC 项目

非常简单,执行这一条命令即可:
tinyrpc/generator/tinyrpc_generator.py -o ./ -i order_server.proto -p 12345是的,你仅仅需要提供 order_server.proto 即可,这里先不介绍各个选项的含义,你可以观察到在当前目录下 `./` 已经生成了项目 order_server ,其项目结构如下:
order_server: 项目根目录
  - bin: 可执行文件目录
    - run.sh: 启动脚本
    - shutdown.sh: 停止脚本
    - order_server: 可执行文件
  - conf: 配置文件目录
    - order_server.xml: TinyRPC 配置文件
  - log: 日志目录,存放运行时产生的日志文件
  - obj: 库文件目录,存放编译过程的中间产物
  - order_server: 源代码文件目录
    - comm: 公共文件
    - interface: 接口定义文件目录,每一个RPC方法会在此处定义一个接口
    - pb: 由 protoc 工具生成的文件,以及源 protobuf 文件
    - service: 接口转发层,将每个 RPC 方法跳转到对应的 interface 接口
      - order_server.cc
      - order_server.h
    - main.cc: main 文件,TinyRPC 服务的 main 函数在此
    - makefile: TinyRPC 工程的 makefile 文件,直接执行 make 即可
  - test_client: 测试工具目录,每一个 interface 下的接口,在此处都会有一个对应的 cleint 工具,可以简单测试 RPC 通信2.3 编译构建 TinyRPC 项目

OK, 你唯一需要做的就是进入 order_server/order_server 目录,直接 make 即可,整个项目就完成构建了(不出意外的话。。。)
cd order_server/order_server && make -j4编译成功后,会在 bin 目录下生成项目可执行文件,以及在 test_client 目录下生成各个 RPC 接口的测试工具。
2.3 运行 TinyRPC 项目以及测试

非常简单,order_server/bin 目录下,运行启动脚本即可.
cd order_server/bin && sh run.sh order_server运行是运行了,but 如何测试是否 RPC 服务运行成功的呢?
当然,TinyRPC 提供了客户端测试工具,在 test_client 目录下,你可以看到每一个 RPC 接口都有对应的测试文件,当 make 成功后,这些测试文件也会生成对应的可执行文件,直接运行即可,例如测试查单接口(query_order_detail)是否正常:
./test_query_order_detail正常的话,你会看到类似如下输出:
ikerli@localhost test_client]$ ./test_query_order_detail_client
Send to tinyrpc server 0.0.0.0:12345, requeset body:
Success get response frrom tinyrpc server 0.0.0.0:12345, response body: res_info: "OK"否则,你会看到失败的具体原因,请根据错误码自行排查。例如这里错误显示为 peer closed,多半是服务没有启动,导致该端口没人监听:
[ikerli@localhost test_client]$ ./test_query_order_detail_client
Send to tinyrpc server 0.0.0.0:12345, requeset body:
Failed to call tinyrpc server, error code: 10000000, error info: connect error, peer[ 0.0.0.0:12345 ] closed.2.4 业务逻辑开发

以上过程都只是框架自身的代码逻辑,而实际的业务逻辑在哪里开发呢?tinyrpc_geneatorProtobuf 文件中的每一个 RPC 方法生成了一个接口(interface), 这些接口位于 order_server/interface/ 目录下:
例如这里的查单方法 query_order_detail 方法, 我们可以在 interface 目录下找到这两个文件http://query_order_detail.cc 和 query_order_detail.h
// interface/query_order_detail.cc

#include "tinyrpc/comm/log.h"
#include "order_server/interface/query_order_detail.h"
#include "order_server/pb/order_server.pb.h"

namespace order_server {

QueryOrderDetailInterface::QueryOrderDetailInterface(const ::queryOrderDetailReq& request, ::queryOrderDetailRsp& response)
  : m_request(request),
  m_response(response) {

    // m_request: 客户端请求的结构体,从中可以取出请求信息
    // m_response: 服务端响应结构体,只需要将结果设置到此即可,TinyRPC 会负责会送给客户端结果
}

QueryOrderDetailInterface::~QueryOrderDetailInterface() {

}

void QueryOrderDetailInterface::run() {
  //
  // Run your business at here
  // m_reponse.set_ret_code(0);
  // m_reponse.set_res_info("Succ");
  //
}
那么写业务逻辑就非常简单了,只需要实现具体的 QueryOrderDetailInterface::run() 方法。
总之,你可以在 run 方法里面实现任何的业务逻辑,包括且不限于拉黑用户、偷偷扣用户钱等。是的,作为业务 boy,你完全可以只写这个函数即可,其他所有东西都不用关心。其他任何逻辑完全不需要关心,TinyRPC 已经处理好了一切,交给它办事你就放心吧。



2.5 Protobuf接口变更怎么办?

当需要升级接口的时候,即修改 Protobuf 文件,要怎么重新生成项目呢?因为你在 interface 目录下实现了业务逻辑,会不会重新生成项目之后,之前的业务代码被覆盖了?
完全不用担心,tinyrpc_generator 已经考虑到了这种情况,你可以放心大胆的修改 Protobuf 文件,然后重新执行生成命令:
tinyrpc/generator/tinyrpc_generator.py -o ./ -i order_server.proto -p 12345tinyrpc_generator 会智能的判断哪些文件需要更新,哪些文件无需更新。规则如下:

  • interface: 下所有的接口定义文件,如果同名文件存在则不会更新,否则生成新文件
  • service: 该目录下的文件每次都会被更新,因为 protobuf 文件修改意味着接口有变化,比如新增或者删除接口之类的,需要重新生成文件以便能对新增的接口进行转发
  • makefile: 不存在时生成,存在则不更新
  • main.cc: 不存在时生成,存在则不更新
  • test_client: 不存在时生成,存在则不更新
  • pb: 每次都会更新(这是必然的,毕竟 protobuf 文件都变了)
2.5 tinyrpc_generator 选项详解

tinyrpc_generator 是用 python 语言实现的简单脚本,其提供了几个简单的命令行入参选项,你也可以使用 -h 或者 --help 选项获取帮助文档:
Options:
-h, --help
    打印帮助文档
-i xxx.proto, --input xxx.proto
    指定源 protobuf 文件,注意只支持 porotbuf3

-o dir, --output dir
    指定项目生成路径

-p port, --input port
    指定 TinyRPC 服务监听的端口(默认是 39999)

-h x.x.x.x, --host x.x.x.x
    指定 TinyRPC 服务绑定的 IP 地址(默认是 0.0.0.0)
ok,到这里你应该明白了 TinyRPC 的正确使用方式了吧。
3. TinyRPC 项目问题反馈

不知不觉 TinyRPC 这个项目已经收获了 369 个 star 了,非常感谢各位同学的支持。目前项目基本主体已经开发完了,预计不会再有较大的代码变更了,后续也将输出更多的原理性文章。
当然,实际在使用过程中肯定也有或多或少的问题。这些问题都是我的锅,放心大胆来找我就好了。
推荐的解决问题的方式:

  • 在GitHub上提 issue(这个就叫专业)
  • 知乎文章评论或者私信(响应可能不是很及时)
  • 加群 260423934 交流
  • 漂亮妹子直接私我加微信  (这个响应最快)
  • 公众号留言
  • 后面有空在建个群吧(看人多不多,先待定)
不推荐的方式:

  • 提问题阴阳怪气的,说脏话的。
  • 理直气壮的,不会百度的。


<hr/>如果您觉得对你有所帮助,请点个关注支持一下。同时 GitHub 项目也麻烦给个 Star 支持下开源精神,感谢各位大佬!!!
GitHub - Gooddbird/tinyrpc: c++ rpc
TinyRPC 内容合集欢迎整理了一个专栏,有兴趣的可以持续关注下:

更多内容欢迎关注我的个人公众号,微信搜索 ikerli
回复

使用道具 举报

2

主题

6

帖子

9

积分

新手上路

Rank: 1

积分
9
发表于 2022-12-21 17:31:36 | 显示全部楼层
继续更新啊
回复

使用道具 举报

2

主题

6

帖子

8

积分

新手上路

Rank: 1

积分
8
发表于 2022-12-21 17:32:28 | 显示全部楼层
好的好的[大笑]
回复

使用道具 举报

2

主题

9

帖子

11

积分

新手上路

Rank: 1

积分
11
发表于 2022-12-21 17:32:52 | 显示全部楼层
不支持window?
回复

使用道具 举报

2

主题

7

帖子

11

积分

新手上路

Rank: 1

积分
11
发表于 2022-12-21 17:33:50 | 显示全部楼层
不支持的
回复

使用道具 举报

1

主题

6

帖子

8

积分

新手上路

Rank: 1

积分
8
发表于 2022-12-21 17:33:57 | 显示全部楼层
你使用的协程是Linux的协程?不是C++最新的协程?
回复

使用道具 举报

2

主题

10

帖子

13

积分

新手上路

Rank: 1

积分
13
发表于 2022-12-21 17:34:14 | 显示全部楼层
大神厉害,欢迎pr吗
回复

使用道具 举报

2

主题

10

帖子

11

积分

新手上路

Rank: 1

积分
11
发表于 2022-12-21 17:35:10 | 显示全部楼层
非常欢迎
回复

使用道具 举报

1

主题

5

帖子

4

积分

新手上路

Rank: 1

积分
4
发表于 2022-12-21 17:35:41 | 显示全部楼层
协程参考的libco实现的,没用c++20的协程。之前有考虑过,但还是感觉还是有栈非对称协程好用一点,对业务代码侵入性也很小。
回复

使用道具 举报

5

主题

10

帖子

20

积分

新手上路

Rank: 1

积分
20
发表于 2022-12-21 17:36:25 | 显示全部楼层
搞个qq或者微信群吧[可怜]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表