一.基本概念
1.本地函数调用
func main() {
var a = 2
var b = 3
result := calculate(a, b)
fmt.Println(result)
return
}
func calculate(x, y int) {
z := x * y
return z
}
分析:
(1)将a和b的值压栈
(2)通过函数指针找到calculate函数,进入函数取出栈中的值2和3,将其赋予x和y
(3)计算x * y,并将结果存在z
(4)将z的值压栈,然后从calculate返回
(5)从栈中取出z返回值,并赋值给result
2.远程函数调用(RPC ---- Remote Procedure Calls)
网上商城和支付服务是两个不同的业务,分别放在不同的网络上,可以从网上商城调用付款的函数,完成支付功能。
RPC需要解决的问题:
(1)函数映射
(2)数据转换成字节流
(3)网络传输
3.RPC概念模型
RPC由5个模型组成:User,User-Stub,RPC-Runtime,Server-Stub,Server
4.一次RPC的完整过程
IDL(Interface description language)文件:IDL通过一种中立的方式来描述接口,使得在不同平台上运行的对象和用不同语言编写的程序可以相互通信。
生成代码:通过编译器工具把IDL文件转换成语言对应的静态库。
编解码:从内存中表示到字节序列化的转换成为编码,反之为解码,也常叫做序列化和反序列化。
通信协议:规范了数据在网络中的传输内容和格式。除必须得请求/相应数据外,通常还会包含额外的元数据。
网络传输:通常基于成熟的网络库走TCP/UDP传输。
5.RPC的好处
(1)单一职责,有利于分工协作和运维开发
(2)可扩展性强,资源使用率更优
(3)故障隔离,服务的整体可靠性更高
二.分层设计
Apache Thrift
1.编解码层
数据格式
语言特定的格式:许多编程语言都内建了将内存对象编码为字节序列的支持,例如Java有java.io.Serializable
文本格式:JSON、XML、CSV等文本格式,具有人类可读性
二进制编码(使用较多):具备跨语言和高性能等优点,常见有Thrift的BinaryProtocol,Protobuf等
TLV编码:
——Tag:标签,可以理解为类型
——Length:长度
——Value:值,Value也可以是个TLV结构
struct Person {
1: required string userName,
2: optional i64 favoriteNumber,
3: optional list<string> interests
}
选型
兼容性:支持自动增加新的字段,而不影响老的服务,这将提高系统的灵活度
通用性:支持跨平台、跨语言
性能:从空间和时间两个维度来考虑,也就是编码后数据大小和编码耗费时长
2.协议层
特殊结束符:一个特殊字符作为每个协议单元结束的标示
变长协议:以定长加不定长的部分组成,其中定长的部分需要描述不定长的内容长度
协议构造
LENGTH:数据包大小,不包含自身
HEADER MAGIC:标识版本信息,协议解析时候快速校验
SEQUENCE NUMBER:表示数据包的seqID,可用于多路复用,单连接内递增
HEADER SIZE:头部长度,从第14个字节开始计算一直到PAYLOAD前
PROTOCOL ID:编解码方式,有Binary和Compact两种
TRANSFORM ID:压缩方式,如zlib和snappy
INFO ID:传递一些定制的meta信息
PAYLOAD:消息体
3.网络通信层
网络库的衡量指标:
(1)提供易用API:封装底层Socket API、连接管理和事件分发
(2)功能:协议支持tcp/udp/uds等、优雅退出异常处理等
(3)性能:应用层buffer减少copy、高性能定时器、对象池等
三.总结
远程过程调用(Remote Procedure Call, RPC)框架是一种允许程序调用另一个地址空间中的子程序或过程的技术,而无需程序员具备网络通信的复杂知识。RPC框架使得分布式计算变得更加简单,因为它将网络通信抽象为普通的函数调用,从而隐藏了底层的网络细节。在多个服务实例间分配客户端请求,提高系统可用性和性能。Thrift是由Facebook开源的软件框架,用于高效创建可跨语言的服务开发。RPC框架通常使用HTTP、TCP等协议进行数据传输。