C# 的轻量级 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 是什么?
- Redola.Rpc 是一个基于 C# 的轻量级 RPC 框架;
- Redola.Rpc 是一个源代码托管在 GitHub 上的开源项目;
- Redola.Rpc 是一个发布在 nuget.org 上的可安装软件包;

源代码开源地址: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 的依赖库
- Cowboy.Sockets 基于 C# 实现的 TCP Socket 类库;
- protobuf-net 支持 .NET 的 Google Protocol Buffers 序列化;
- Logrila.Logging 日志框架适配器;
有那么多 RPC 框架,为什么要自己写一个?
演进出来的,那就是一个故事了。
起初,我们作为一个初创公司,还在尝试思考清楚我们要做的东西究竟应该是什么样子,毕竟市场上少有同类竞品,那么首先设计一个原型是合理的。所以,我们只有一个应用程序,用于定时拉取第三方合作伙伴的 WebService 数据,并通过设计的算法进行计算处理,然后写入数据库;

有了数据,总要找地方展现吧,于是招聘了 Unity3D 前端开始做炫酷的 App,有实时数据推送的展现要求,所以前后端通信使用了 WebSocket 协议,也就产生了 Cowboy.WebSockets;

第三方合作伙伴的 WebService 显然不只一个接口,多个接口并发拉取,每 100 毫秒拉取一次,线程繁忙影响了计算处理和写入数据库;好,将数据拉取分离出去,并进行前期的数据清洗和过滤,然后再发给算法计算引擎;这时,就有了 2 个服务,一个负责拉取数据 Feed,一个负责计算入库 Engine,通过 Cowboy.Sockets 进行 TCP 消息通信;

终于有更多的数据可供展现了,当然 U3D App 也快开发完成了,App 不可能就装在一个手机上吧,万一发布到 AppStore 上火了呢?引入了接入层 Gateway 系列服务,用于保持 WebSocket 长连接和数据推送;好,现在有了 2 + n 个服务了,并且 n > 5 还做了软负载均衡;

算法引擎 Engine 计算完后,要将数据分发到这 n 个 Gateway 服务上,臣妾就这两颗 CPU,着实做不到啊!分发成了瓶颈,万一 n 成长到 50 怎么办?好,将数据推送委托给新服务 Bolt 服务,专门做推送给 Gateway;

引擎算法发现需要更多输入源数据参与计算,好吧,引入更多第三方数据 Feed 提供商,每家一个服务做拉取;艾玛~ 每家实际上是多个服务拉取~ 还有要求主动推送的 ~

哎呀,对于同一领域对象,每家的描述 ID 显然不一样,毕竟不是一个公司,手工匹配好烦,眼睛都快瞎了,做个 Mapping 自动服务根据特征专门负责匹配 ID,匹配好了再发给引擎,妈妈再也不用担心我的 ID;

数据简直不要太多,计算引擎 Engine 边计算边入库,常年 100% CPU 啊我的哥;拆!先将预处理数据入库,再将计算的结果入库;

什么?数据库写入有延迟?线程被阻塞,又跟我的 CPU 过不去!拆,引流写操作到 MQ 消息队列,加上 Durability 落地,爱阻塞谁阻塞谁,爱啥时候写啥时候写。

隔壁老王看了一眼我们的 U3D App,矮油不错哦,狂拽酷霸吊炸天啊!你们这数据算法和计算引擎有些超出我的知识范围,我有一些新的产品想法,要么你们帮我实现 H5,要么你们提供 API 我们自己实现 H5,反正我的想法必须实现,你看这是 20% 预付款你们下个星期能不能上线 API 啊?王哥,有钱还能有办不成的事儿?是吧,说,你都要啥推送接口?Socket + Protobuf 可以吧?HTTP 也行?

刚回国的尼古拉斯赵四听闻有 API 开放能力,那必须接入啊,共享经济实现共赢嘛,有钱大家一起赚,只是这 API 接口能不能修改成 RESTful + 反向 POST?

我相信,明天还会有新需求的!要善待今天的自己,底层封装成 Redola.Rpc 框架!
C# 的轻量级 RPC 框架的更多相关文章
- 微博轻量级RPC框架Motan
Motan 是微博技术团队研发的基于 Java 的轻量级 RPC 框架,已在微博内部大规模应用多年,每天稳定支撑微博上亿次的内部调用.Motan 基于微博的高并发和高负载场景优化,成为一套简单.易用. ...
- 微博轻量级RPC框架Motan正式开源:支撑千亿调用
支撑微博千亿调用的轻量级 RPC 框架 Motan 正式开源了,项目地址为https://github.com/weibocom/motan. 微博轻量级RPC框架Motan正式开源 Motan 是微 ...
- 轻量级RPC框架开发
nio和传统io之间工作机制的差别 自定义rpc框架的设计思路 rpc框架的代码运行流程 第2天 轻量级RPC框架开发 今天内容安排: 1.掌握RPC原理 2.掌握nio操作 3.掌握netty简单的 ...
- 基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇
基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇 前提 最近对网络编程方面比较有兴趣,在微服务实践上也用到了相对主流的RPC框架如Spring Cloud Gateway底层也切换 ...
- 基于Netty和SpringBoot实现一个轻量级RPC框架-Server篇
前提 前置文章: Github Page:<基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇> Coding Page:<基于Netty和SpringBoot实现 ...
- 基于Netty和SpringBoot实现一个轻量级RPC框架-Client篇
前提 前置文章: <基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇> <基于Netty和SpringBoot实现一个轻量级RPC框架-Server篇> 前 ...
- 基于Netty和SpringBoot实现一个轻量级RPC框架-Client端请求响应同步化处理
前提 前置文章: <基于Netty和SpringBoot实现一个轻量级RPC框架-协议篇> <基于Netty和SpringBoot实现一个轻量级RPC框架-Server篇> & ...
- JRPC 轻量级RPC框架
JRPC是一个轻量级的java RPC框架.它支持服务注册和发现. 目前它开源了,地址为:https://github.com/dinstone/jrpc. Quick Start step 1: g ...
- Netty + Spring + ZooKeeper搭建轻量级RPC框架
本文参考 本篇文章主要参考自OSCHINA上的一篇"轻量级分布式 RPC 框架",因为原文对代码的注释和讲解较少,所以我打算对这篇文章的部分关键代码做出一些详细的解释 在本篇文章中 ...
随机推荐
- Windows 8.1 归档 —— Step 1 选择与安装
下面是 Windows 8.1 各版本区别: Windows 8.1 标准版(一般就称之为Windows 8.1): 包括全新的 Windows 商店.Windows 资源管理器.任务管理器等等,还将 ...
- Jersey(1.19.1) - Extracting Request Parameters
Parameters of a resource method may be annotated with parameter-based annotations to extract informa ...
- streams 日差管理及监控
第一部分 stream环境的日常管理 1.capture进程管理 --capture进程信息 SET LINESIZE 200 COLUMN CAPTURE_NAME HEADING 'Capture ...
- IOS UITabelView的cell
一.Cell的重用原理 iOS设备的内存有限,如果用UITableView显示成千上万条数据,就需要成千上万个UITableViewCell对象的话,那将会耗尽iOS设备的内存.要解决该问题,需要重用 ...
- MSSQL 数字钱转化为大写
--说明: --1.本函数范围从 毫 ~ 兆 --2.有四种精度(元,角 ,分,厘 ,毫) --3.有三种进位规则(四舍五入,接舍去,非0就入) --参数说明:dbo.MoneyToCapital( ...
- jQuery实现CheckBox全选、全不选
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- (转)基于Redis Sentinel的Redis集群(主从&Sharding)高可用方案
转载自:http://warm-breeze.iteye.com/blog/2020413 本文主要介绍一种通过Jedis&Sentinel实现Redis集群高可用方案,该方案需要使用Jedi ...
- (转)使用SVN+CruiseControl+ANT实现持续集成之一
在前面的文章中, 介绍自己当时所在团队的处境(使用.NET开发),一个不到十个人的研发团队在保证正常开发进度同时需要并发支持四.五十个项目问题处理,经常为了程序版 本冲突.日常测试版本.发布版本提供等 ...
- 引用类型之Array类型
Array类型 ECMAScript数组与其它语言数组一样,都是数据的有序列表.但是ECMAScript数组的每一项可以保存任何类型的数据.而且,ECMAScript数组是可以动态调整的. 1.创建和 ...
- [C#]线程处理
线程处理用于使程序能够执行并发处理,同时执行多个操作.C#中有三种线程的使用方法,BackgroundWorker组件.线程池.自己创建使用线程,接下来分别介绍如何使用. 1.使用Background ...