支持多语言的RPC框架—GRPC

902 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

前言

之前公司用的grpc做rpc远程调用的框架,这个框架我也是第一次用,是用gradle做jar包管理的,之前一直是在用maven仓库,都是做jar包管理的其实主要功能还是一样的,需要在下面就来介绍下为什么要用grpc,以及它的好处。

GRPC简介

根据官方文档上的介绍

  • Grpc 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持.
  • Grpc 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用

grpc_concept_diagram_00.png

RPC服务分,server端和client端

在grpc里面客户端可以像调本地方法一样去调远程服务端的方法,相当于如果客户端想调服务端的方法,那么在客户端就要定义一个和服务端一样的方法,包括入参的结构和出参的返回类型都要一样,rpc框架比如我们常用的dubbo。

因为是跨语言的所以上图可以解释为:Ruby client 和 Android-Java client作为grpc的客户端去请求,grpc Server通过protobuf进行请求和接收。

GRPC的性能优势

1.gRPC消息使用一种有效的二进制消息格式protobuf进行序列化。Protobuf在服务器和客户机上的序列化非常快。Protobuf序列化后的消息体积很小,能够有效负载,在移动应用程序等有限带宽场景中显得很重要。

2.gRPC相比http的rest传输json、xml,可读性并不是很高。

3.gRPC是为HTTP/2而设计的,它是HTTP的一个主要版本,与HTTP 1.x相比具有显著的性能优势

4.二进制框架和压缩。HTTP/2协议在发送和接收方面都很紧凑和高效。 通过单个TCP连接复用多个HTTP/2调用。多路复用消除了线头阻塞。

GRPC使用

gRPC 默认使用 /protocol buffers/,这是 Google 开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如 JSON)。正如你将在下方例子里所看到的,你用 /proto files/ 创建 gRPC 服务,用 protocol buffers 消息类型来定义方法参数和返回类型

首先需要在idea中配置gradle,之前项目中用的grad le版本是5.2.1。

786AFBF5-4ACB-403D-BB00-EA6C98D4D273.png

接下来就是要创建子项目,创建proto目录,并且是创建后缀为.proto的文件

47134076-EF10-44CF-8756-FC2691302A7C.png

protobuf示例

syntax = "proto3"; // 指定版本 必须
option java_multiple_files = true; // 是否生成多个文件 可选 默认false 如果为true 则会根据实体 service生成多个不同的文件 否则只会根据service生成不同的文件
option java_package = ""; // 指定文件的package名称
option java_outer_classname = ""; // 输出的class名称

package com.test.grpc.api;

import "google/protobuf/empty.proto";

//定义服务接口
service TestService {	
	rpc saveApply (GReqModel) returns (google.protobuf.Empty) {}
}
message GReqModel{
string role =1;      //字符串类型
 bool status = 2;    //布尔类型
 int32 scores = 3;   //int类型
map<string, string> tags = 100; // 支持map类型的属性定义key-value
}

这里 returns google.protobuf.Empty 表示是没有返回参数类型的方法,如果需要有返回类型的参数,可以定义

//定义服务接口
service TestService {	
	rpc saveApply (GReqModel) returns (GResultModel) {}
}
message GReqModel{
string role =1;      //字符串类型
 bool status = 2;    //布尔类型
 int32 scores = 3;   //int类型
map<string, string> tags = 100; // 支持map类型的属性定义key-value
}

message GResultModel{
 string id =1;      //字符串类型
}

定义proto文件,可以使用bulid module 构建我们的功能块 前面提到 option java_package = ""; // 指定文件的package名称 会根据我们配置的路径不同,自己构建到我们对应的目录下

F26197CE-DCD3-49DD-A5BC-1D679C6C3F31.png

形成一个grpc规范的服务接口。

CC4A1687-4FA8-49F0-9A1E-321EAE96D802.png

当然我们去用这个服务接口的时候,只需要去实现这这个接口,然后通过Java去重写这个方法,就能作为服务端的接口给客户端调用,@grpcClient这个注解主要是声明服务方的一个服务名称,方便客户端找到对应的服务。

7B878561-4B21-40F9-AED1-5720E6B6DD64.png