C# 的轻量级 RPC 框架

时间:2021-10-04 02:16:01

Redola.Rpc 的一个小目标 Redola.Rpc 的一个小目标

Redola.Rpc 的一个小目标:20000 tps

Concurrency level: 8 threads Complete requests: 20000 Time taken for tests: 0.886 seconds Time per request: 0.044 ms (avg) Requests per second: 22573 [#/sec] (avg)

Concurrency level: 8 threads Complete requests: 10000 Time taken for tests: 0.424 seconds Time per request: 0.042 ms (mean) Requests per second: 23584 [#/sec] (avg)

测试环境使用 AWS 虚拟机 AWS EC2 C4 Instance Model c4.2xlarge,配置如下:

Processor: Intel(R) Xeon(R) CPU E5-2666 v3 @ 2.90GHz vCPU: 8 Memory: 15 GiB Storage: 30G EBS-Only Bandwidth: 1,000 Mbps OS: Windows Server 2012 R2

Redola.Rpc 是什么?

  源代码开源地址:https://github.com/gaochundong/Redola

  样例测试代码:https://github.com/gaochundong/Redola/tree/master/Tests

Redola.Rpc 的特点

简单粗暴,一看就懂;

简单的注册中心,消除配置障碍;

支持 Request / Response 阻塞模型;

支持任意服务间的消息推送;

内置 protobuf 序列化,提供可替换接口;

Redola.Rpc 内部结构

Redola.Rpc 基于 Cowboy.Sockets 进行构建,使用 TCP Socket 进行服务间通信,默认使用 .NET APM TCP Socket 模式。通过 Actor 模型抽象封装 Socket 连接与交互,实现 Actor 之间的 Register、Lookup、Handshake、KeepAlive 等功能;

Redola.Rpc 概念模型

Actor Peer:代表一个 Actor 节点,任意 Actor 之间均可通信;

Actor Master:作为 Actor 节点注册中心,用于服务的注册与发现;

Actor Identity:一个 Actor 的身份描述,包括 Type、Name、Address、Port 等;

RPC Service:用于实现具体的 RPC 服务,一个 Actor 可以注册多个 RPC Service;

Redola.Rpc 通信模型

Actor Peer 与 Actor Peer 之间通过 TCP 长连接进行通信。Actor 封装了 TCP 中关于 TcpClient 和 TcpServer 的抽象,对外不再暴露 Client 和 Server 的概念,仅以 Peer 呈现,Peer 与 Peer 之间是平等的。Actor Master 与其他 Peer 的区别仅是承担了 Register 和 Lookup 的职责。

Actor Peer 间通过 Actor Master 查询到需要通信的对端 Actor Peer 的 Actor Identity,会首先进行 Handshake 交换 Actor Identity,用以记录对方的身份。Handshake 之后,即可进行预定义注册的 RPC 消息通信。

为掌握对端 Peer 的活跃情况,通过内置的 KeepAlive 机制进行服务间保活,每隔约定时间进行消息交互,若超时时间内未获得保活回复,则自动断开连接。KeepAlive 同时做了一定的优化,若服务间在保活时间内有任何 Send 或 Receive 消息操作,则视为有服务间通信,即对端为活跃状态,会延迟发送保活请求。

假设 Actor 1 (Tyep:hello, Name:hello-001, Address:192.168.1.139, Port:8888) 需要与 Actor 2 (Type:world, Name:world-001, Address:192.168.1.158, Port:7777) 进行通信,则仅需发送消息时指定 Actor 2 的身份 (world, world-001),其中 world 为 Actor 2 的类型,world-001 为该 world 类型下名称为 world-001 的 Actor Peer。

Redola.Rpc 基本契约

任意 Actor 均需向 Actor Master 注册,提供自身 Actor Identity 信息;

仅指定 Actor Type 发送消息,则会随机 Lookup 一个该 Type 的 Actor 进行通信;

Actor 不区分 Client 和 Server 角色,角色由使用者设计;

RPC 调用接口有同步和异步之分,由使用者选择;

支持 Request/Response 同步阻塞模式,可设置阻塞超时时间;

消息注册后,通过反射匹配消息处理方法,On + MessageType 契约编程;

RPC 限流在消息处理侧实施,默认 RateLimiter 限制 CPU 相同数量线程;

内部 TCP 配置 Buffer Pool 连续内存会伴随连接数和吞吐增加,单 Buffer 8K 大小;

若 RPC 传递消息大于 84K,.NET 将 Buffer 分配到 LOH 上,GC 未必及时回收;

Redola.Rpc 的依赖库 有那么多 RPC 框架,为什么要自己写一个?

演进出来的,那就是一个故事了。

起初,我们作为一个初创公司,还在尝试思考清楚我们要做的东西究竟应该是什么样子,毕竟市场上少有同类竞品,那么首先设计一个原型是合理的。所以,我们只有一个应用程序,用于定时拉取第三方合作伙伴的 WebService 数据,并通过设计的算法进行计算处理,然后写入数据库;