概述
RPC主要目的在于让开发者,能够方便的调用远程服务器上的服务,而不需要关注底层的网络通信细节。其是一种进程间通信技术,允许程序在不同计算机上执行代码。
RPC技术主要用于分布式系统、微服务架构以及需要进行跨网络调用服务的应用中。
基本原理
- 客户端发送请求
- 客户端的RPC框架将调用远程计算机的过程,封装成一个请求消息,发送给服务器
- 服务器处理请求
- 服务器的RPC框架接收请求消息,解封装消息,同时调用对应的服务方法
- 服务端发送响应
- 当服务端处理完该消息后,服务器的RPC框架将结果封装成响应消息,发送给客户端
- 客户端接收响应
- 客户端接收到服务端的消息后,解封装该消息,然后将结果返回给客户端代码使用
RPC框架
- gRPC:由Google开发,基于HTTP/2和Protobuf(Protocol Buffers)序列化协议,支持多种编程语言。
- Apache Thrift:由Facebook开发,支持多种编程语言和传输协议。
- XML-RPC:基于XML和HTTP协议,简单易用,跨语言支持好。
- JSON-RPC:基于JSON和HTTP协议,易于使用和调试。
gRPC
gRPC即是Google开发的RPC框架
特点总结
- 高性能:基于HTTP/2协议,支持双向流、头部压缩、多路复用
- 跨语言支持:不同语言之间的系统支持进行通信
- 强类型:Protobuf作为接口定义语言和数据序列化协议
- 双向流:客户端与服务端双向流、适用于实时通信
- 负载均衡:内置多种负载均衡策略,提高系统可靠性和可拓展性
Protocol Buffers(Protobuf)
相比于XML和JSON,Protobuf序列化和反序列化的速度更快,占用空间更小
用于数据的序列化和反序列化,定义消息格式和数据结构,同时通过编译器生成相应代码
- 组成
- .proto文件:定义数据结构和服务接口文件,其中包括消息类型和RPC服务的定义
- 编译器:将.proto文件编译成目标语言的代码,供应用程序使用
.proto文件解释
- syntax = "proto3":指定使用Protocol Buffers的版本3
- service Greeter:定义一个名为Greeter的RPC服务,其中包含一个名为SayHello的方法
- rpc SayHello (HelloRequest) returns (HelloReply):定义一个RPC方法SayHello,它接收一个HelloRequest消息并返回一个HelloReply消息
- message HelloRequest和message HelloReply:定义两个消息类型,分别包含一个字符串字段
gRPC与Reactor
- 应用场景分析
- gRPC:构建分布式系统以及微服务架构,为其提供接口,所以只需要关注其系统逻辑,而不需要关注底层通信的细节
- Reactor:主要用来解决并发I/O问题,构建高性能、低延迟的网络服务器
- 实现机制:
- gRPC:封装底层通信细节,借助Protobuf定义使用接口以及消息格式,通过生成代码进行服务调用和消息处理,其底层是基于HTTP2进行通信
- Reactor:基于事件循环和回调机制,管理IO事件的分发和处理,从而实现高效的事件驱动架构
- 理解
- gRPC:是一种从高层构建通信框架,通过提供的接口,从而简化分布式系统中服务之间的通信。其主要目标在于提高服务
- Reactor:基于底层的一种设计模式,主要是用于处理并发IO操作
思考gRPC和Reactor结合的可能性
- 首先Reactor构建在服务端,主要负责监听新连接的IO请求,当监听的请求发生的时候,则将其交付给其他线程处理。
- gRPC则是负责处理具体业务。
- 所以,借助Reactor来管理大量并发连接,从而实现高效的分发事件。然后响应的I/O事件交付给gRPC框架进行处理,由gRPC框架来处理具体的业务。
构建RPC框架
步骤分析
- 定义通信协议
- 消息格式:选择一种轻量级的数据格式进行消息传递,可以选择JSON或Protobuf进行消息传递
- 请求和响应格式:定义好通信双方的请求和响应结构
- 传输方式确认
- 选择传输协议:TCP HTTP
- 套接字编程:服务端和客户端使用套接字编程,从而建立连接发送接收数据
- 服务端设计
- 远程调用方法初始化:服务器注册可供远程调用的方法,可以使用哈希表来存储方法名称与对应的函数指针或者回调函数
- 请求处理:服务器要能够解析客户端发送的请求,调用对应的方法并返回结果。在需要处理并发连接的时候,可以使用异步I/O来处理多个客户端连接
- 序列化/反序列化:将收到的请求数据进行序列化为特定的请求结构进行U存储,同时将结果序列化为响应数据返回给哭护短
- 客户端设计
- 调用远程方法:客户端封装远程方法的调用,将方法的名称以及参数打包成请求,发送给服务器,同时等待服务器响应
- 接收响应:客户端接收服务器响应后,进行反序列化,处理返回结果或者错误信息
- 异步调用(看情况选择):客户端可以通过异步调用从而提高性能,避免同步调用导致阻塞
细节问题 补充
大量并发连接处理方法:
可以使用多线程或者异步I/O来处理大量的并发连接。多线程模型可以使用功能线程池,每个线程负责处理一个客户端的连接;异步I/O则借助事件驱动机制来处理多个连接。
确保数据传输和可靠性以及完整性:
- 使用传输层协议(TCP)保证数据传输的可靠性以及顺序性
- 应用层可以使用效验机制(校验和、数据长度前缀)确保数据完整性
- 安全性保证:使用TLS/SSL来加密传输层的数据,从而保证通信机密性和完整性,同时还可以在应用层实现身份认证机制
实现方法注册和调用的方法
- 借助哈希表来存储方法名称和对应函数指针或回调函数(方法:函数)
- 服务器接收请求后,通过方法名称查找对应的函数,并调用该函数
如何处理参数类型的多样性和返回值
- 使用通用的数据格式,例如JSON和Protobuf来表示多种类型的数据
- 通过序列化和反序列化机制,可以将参数和返回值转换为标准格式传输
如何实现负载均衡和容错
- 在多台服务器上部署RPC服务时,使用功能负载均衡器分配请求
- 实现服务注册以及发现机制,动态的调整服务实例,从而提高系统的可用性和容错能力
性能优化方法
- 优化网络I/O性能,使用异步IO模型
- 减少序列化和反序列化的开销,选择高效且轻量化的序列化格式
- 使用连接池,复用客户端到服务器的连接
- 实现批量请求和响应,减少网络往返的次数,从而提高性能
gRPC 和 RPC对比
gRPC相比于RPC的优势;现代分布式系统中选择gRPC的原因
- 高性能:并非是基于HTTP1.1协议,而是基于HTTP2 协议,支持多路复用、流控制、头部压缩等功能
- 多语言支持:gRPC支持多种编程语言,便于不同语言的系统间通信
- 强类型接口:使用Protobuf作为接口定义语言,提供强类型的接口和数据验证
- 流式通信:支持双向流,适用于实时通信的场景
- 负载均衡和名称解析:内置支持多种负载均衡策略和服务发现机制
Protobuf 优势
- 高效:Protobuf的序列化和反序列化速度快且轻量化
- 强类型:通过定义.proto文件,生成强类型代码,提供编译时进行检查
- 拓展性强
- 扩语言支持
gRPC的工作机制以及如何实现同步与异步调用
- 工作机制:gRPC基于HTTP2协议进行通信,使用Protobuf定义接口和消息格式。客户端调用远程方法的时候,通过该框架生成的代码将方法调用转换为网络请求,发送到服务器中。服务器接收请求,调用相应方法并返回结果。
- 同步调用:客户端调用方法的时候等待服务器返回结果
- 异步调用:客户端不一直等待结果,而是通过回调进行处理
gRPC流式通信的实现以及使用场景
- 实现方式分析:gRPC基于HTTP2的流特征,实现了客户端流、服务器流和双向流。客户端可以在一个长连接中进行多次消息的发送和接收。
- 场景:实时通信、数据流处理、聊天系统等需要持续交换数据的场景
gRPC的负载均衡和服务发现
- 负载均衡:例如可以使用轮询或者哈希实现负载均衡策略;通过服务发现系统动态获取可用服务实例列表,并根据策略分配请求
- 服务发现:主要是集成服务注册与发现框架,gRPC 客户端可以自动获取和更新可用的服务器列表,从而实现动态负载均衡
gRPC的性能优化
- 多路复用:基于HTTP2协议,支持多路复用,减少连接开销
- 头部压缩:HTTP2减少了重复的头部,提高了传输效率
- 连接池:使用连接池复用TCP连接,减少连接建立和断开的开销
- 批量请求:通过合并小的请求和响应,减少网络往返次数,从而提高吞吐量