gRPC
何为 RPC
-
RPC 和 HTTP 的关系
- 基于 HTTP 的远程调用方案(包含了接口规范、序列化反序列化等)和 RPC 是并列的
- 单从 HTTP 协议来看,RPC 可以使用 HTTP 作为通信协议
-
基于 HTTP 的远程调用方案和 RPC 的相同点、不同点
- 相同点
- 都可以实现远程调用(上图的顶端节点)
- 不同点
- 基于 HTTP RESTful 的远程调用可读性更好
- RPC 可以针对场景选用不同的框架(如 Dubbo、gRPC 等),不同的通信协议(HTTP、TCP、UDP),以及不同的序列化方式(JSON、PB 等),效率更高
- 相同点
-
RPC 执行流程:调用方和被调用方
- Client 调用以本地调用方式调用服务;
- Client Stub 接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体(桩代码是未实现的接口,此处使用动态代理);
- Client Stub 找到服务地址,并将消息发送到服务端;
- Server Stub 收到消息后进行解码;
- Server Stub 根据解码结果调用本地的服务;
- 本地服务执行并将结果返回给 Server Stub;
- Server Stub 将返回结果打包成消息并发送至消费方;
- Client Stub 接收到消息,并进行解码;
- Client 得到最终结果
- Stub (桩代码)指满足形式要求但没有实现实际功能的占位或代理代码
- RPC 中的桩代码负责远程请求或响应
ProtocolBuffer
- PB 是一种语言无关、平台无关、可扩展的序列化结构数据的接口描述语言(Interface Description Language, IDL),可用于通信协议、数据存储等
- 编写
.proto
文件,假设场景是根据地址,查询地址对应的联系方式,以及该号码是否活跃
syntax = "proto3" // 语法版本
package com.hit.demo;
service PhoneLookup {
rpc QueryPhoneByAddress (Request) returns (Response) {}
}
message Requset {
required string id = 1; // required:必须传入1个参数
optional string name = 2; // optional:可以传入0或1个参数,如果不传入则为默认0值
repeated string address = 3; // repeated:可以传入0或多个参数
}
message Response {
string id = 1;
ResultCode result = 2 [default = SUCCESS]; // 声明默认值
repeated int64 number = 3;
repeated bool active = 4;
enum ResultCode {
SUCCESS = 0;
FAIL = 1;
UNKNOWN = 3;
}
}
- 编译
.proto
文件得到桩代码,此时在文件中声明的类已可用,并支持序列化、反序列化
public static void main(String[] args) {
// 构造查询请求
Request req0 = Request.newBuilder()
.setId("Request01")
.setName("dino")
.setAddress(Collections.singletonList("hita08"))
.build();
// 序列化
byte[] reqBytes = req.toByteArray();
// 反序列化
Request req1 = Request.parseFrom(reqBytes);
}
- Client 和 Server 使用编译生成的桩代码,分别实现业务逻辑