gRPC的简单使用
前言
八月初的时候,在公司内部做了一个主题为《gRPC的简单使用》的分享,其实就是和小伙伴们扯扯淡,现在抽空回忆一下,也算是一个小小的总结吧。
现在市面上耳熟能详的RPC框架也很多,下面列举几个遇到比较多的。
- 谷歌的gRPC
- 推特的Thrift
- 阿里的Dubbo
- 。。。。
它们都是支持多语言的,相对来说,这三个之中,Dubbo支持的语言略微少一点。现在在一个公司内都能见到多种语言的技术栈都已经是十分常见的事了,好比我司,都有JAVA,C#,Python三种语言了,所以在多语言支持这方面,在技术选型的时候,肯定是要有所考虑的。
下面进入正式的主题,gRPC。
gRPC的简单介绍

gRPC是一个现代的开源高性能RPC框架,可以在任何环境中运行。它可以高效地将数据中心内和跨数据中心的服务连接起来,并支持可插拔的负载平衡、跟踪、健康检查和身份验证。同时,它还把设备,移动应用程序和浏览器连接到后端服务的分布式计算变得很容易。
gRPC有什么优点呢?
- 简单的服务定义 (使用Protocol Buffers定义服务,这是一个功能强大的二进制序列化工具集和语言)
- 跨语言和平台工作 (在微服务式架构中有效地连接多语言服务(10+种语言支持)并能自动为各种语言和平台的服务生成惯用的客户端和服务器存根)
- 快速启动并扩展 (使用单行安装运行时和开发环境,并使用框架每秒扩展到数百万个RPC)
- 双向流媒体和集成的身份验证 (双向流媒体和集成的身份验证 基于http/2的传输的双向流和完全集成的可插拔身份验证)
gRPC在使用的时候有4种模式供我们选择
- 一元RPC(Unary RPCs ):这是最简单的定义,客户端发送一个请求,服务端返回一个结果
- 服务器流RPC(Server streaming RPCs):客户端发送一个请求,服务端返回一个流给客户端,客户从流中读取一系列消息,直到读取所有消息
- 客户端流RPC(Client streaming RPCs ):客户端通过流向服务端发送一系列消息,然后等待服务端读取完数据并返回处理结果
- 双向流RPC(Bidirectional streaming RPCs):客户端和服务端都可以独立向对方发送或接受一系列的消息。客户端和服务端读写的顺序是任意。
我们要根据具体的场景来决定选择那一种。
这里只介绍一元RPC。正常来说,一元RPC应该可以满足我们日常60~70%的需求了吧。
基本用法
gRPC的基本用法可以简单的分为三个点:
- 服务的定义,即proto文件的编写
- 服务端代码编写
- 客户端代码编写
下面我们依次来看一下
服务的定义
既然要定义一个服务,肯定是知道了这个服务要完成什么事之后。
在定义之前,要对proto3和proto2有所了解。不过proto3是推荐的格式。所以我们基本上只要用proto3就可以了。
下面先来看一个后面要用到的proto文件。
syntax = "proto3";
option csharp_namespace = "XXXService";
package UserInfo;
service UserInfoService {
rpc GetList(GetUserListRequest) returns (GetUserListReply){}
rpc GetById(GetUserByIdRequest) returns (GetUserByIdRelpy){}
rpc Save(SaveUserRequest) returns (SaveUserReply){}
}
message GetUserByIdRequest {
int32 id = 1;
}
message GetUserByIdRelpy{
int32 id = 1;
string name = 2;
int32 age = 3;
int64 create_time = 4;
}
message GetUserListRequest {
int32 id = 1;
string name = 2;
}
message GetUserListReply {
message MsgItem {
int32 id = 1;
string name = 2;
int32 age = 3;
int64 create_time = 4;
}
int32 code = 1;
string msg = 2;
repeated MsgItem data = 3;
}
message SaveUserRequest {
string name = 1;
int32 age = 2;
}
message SaveUserReply {
int32 code = 1;
string msg = 2;
}
它有下面的几个部分
- syntax , 指定要用那个版本的语法
- service , 指定rpc服务的接口,简单理解成我们平时定义的接口
- message , 指定要传输的消息体,简单理解成我们平常用的 DTO
- package , 指定包名
- option , 可选参数的定义,不同语言有不同的选项
其实看上去还是比较容易懂的。至少一眼看过去能知道是些什么意思。
如果对proto3还没有了解的,可以参考这个文档Language Guide (proto3),里面很清楚的介绍了一些数据类型和不同语言数据类型的对应关系。
这里有一个要注意的是,时间类型,在proto3中,没有datetime类型,过去很长一段时间,我们是只能用时间戳来表示时间,也就是定义一个长整型,现在是可以用timestamp表处理了。
在写服务端和客户端代码之前,我们需要根据proto文件生成对应的代码。
一个命令即可搞定。
protoc --proto_path=IMPORT_PATH \
--cpp_out=DST_DIR \
--java_out=DST_DIR \
--python_out=DST_DIR \
--go_out=DST_DIR \
--objc_out=DST_DIR \
--csharp_out=DST_DIR \
path/to/file.proto
现在时代进步的这么快,不少语言已经有工具做了集成,可以在build项目的时候就生成对应的文件了,不需要我们再单独去执行一次上面的那个命令。
好比我们的.NET项目,可以在ItemGroup中直接指定Protobuf,然后告诉它,proto文件是那个,是要生成服务端代码还是客户端代码。
可以看看下面这个具体的例子。
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Protobuf Include="Protos\userinfo.proto" GrpcServices="Server" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" />
<PackageReference Include="Google.Protobuf" Version="3.8.0" />
<PackageReference Include="Grpc.Core" Version="1.22.0" />
<PackageReference Include="Grpc.Tools" Version="1.22.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
再往下,就是写代码了。
服务端代码编写
服务端代码分两部分,一部分是服务具体的实现,一部分是服务怎么起来。
先来看看服务的具体实现。
namespace MyBasedServiceA
{
using Grpc.Core;
using System.Linq;
using System.Threading.Tasks;
public class UserInfoServiceImpl : UserInfoService.UserInfoServiceBase
{
public override Task<GetUserByIdRelpy> GetById(GetUserByIdRequest request, ServerCallContext context)
{
var result = new GetUserByIdRelpy();
var user = FakeUserInfoDb.GetById(request.Id);
result.Id = user.Id;
result.Name = user.Name;
result.Age = user.Age;
result.CreateTime = user.CreateTime;
return Task.FromResult(result);
}
public override Task<GetUserListReply> GetList(GetUserListRequest request, ServerCallContext context)
{
var result = new GetUserListReply();
var userList = FakeUserInfoDb.GetList(request.Id, request.Name);
result.Code = 0;
result.Msg = "成功";
result.Data.AddRange(userList.Select(x => new GetUserListReply.Types.MsgItem
{
Id = x.Id,
Age = x.Age,
CreateTime = x.CreateTime,
Name = x.Name
}));
return Task.FromResult(result);
}
public override Task<SaveUserReply> Save(SaveUserRequest request, ServerCallContext context)
{
var result = new SaveUserReply();
var flag = FakeUserInfoDb.Save(request.Name, request.Age);
result.Code = 0;
result.Msg = "成功";
return Task.FromResult(result);
}
}
}
可以看到上面的代码,我们只要继承由proto文件生成的一个基类,然后去重写它的实现,就可以认为是实现了一个服务。这个其实就是写我们具体的业务逻辑,大boss有什么需求,堆上去就好了。
然后来看第二部分,服务怎么起来。
在这里我选择的方案是使用通用主机来跑。当然也可以直接在Startup的Configure方法中去启动服务。只要能起来就行
gRPC的简单使用的更多相关文章
- gRPC的简单Go例子
gRPC是一个高性能.通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发 ...
- grpc的简单用例 (golang实现)
这个用例的逻辑很简单, 服务器运行一个管理个人信息的服务, 提供如下的四个服务: (1) 添加一个个人信息 注: 对应于Unary RPCs, 客户端发送单一消息给服务器, 服务器返回单一消息 (2) ...
- grpc的简单用例 (C++实现)
这个用例的逻辑很简单, 服务器运行一个管理个人信息的服务, 提供如下的四个服务: (1) 添加一个个人信息 注: 对应于Unary RPCs, 客户端发送单一消息给服务器, 服务器返回单一消息 (2) ...
- DotnetCore下Grpc的简单使用(基于3.0版本)
目录: 一.简单介绍DotnetCore3.0如何将.proto文件生成对应的服务端和客户端类 二.介绍如何在服务端使用Grpc,以及Grpc需要的条件(HTTP2.TLS) 三.介绍如何创建Grpc ...
- 学习GRPC(一) 简单实现
Grpc 实现流程图 资料 https://grpc.io/docs/quickstart/go/ https://studygolang.com/articles/16627 使用方法 make r ...
- Go微服务 grpc的简单使用
作者:薇文文链接:https://www.jianshu.com/p/20ed82218163来源:简书 准备工作 先安装Protobuf 编译器 protoc,下载地址:https://github ...
- Go语言入门篇-gRPC基于golang & java简单实现
一.什么是RPC 1.简介: RPC:Remote Procedure Call,远程过程调用.简单来说就是两个进程之间的数据交互. 正常服务端的接口服务是提供给用户端(在Web开发中就是浏览器)或者 ...
- ASP.NET Core 3.0 上的gRPC服务模板初体验(多图)
早就听说ASP.NET Core 3.0中引入了gRPC的服务模板,正好趁着家里电脑刚做了新系统,然后装了VS2019的功夫来体验一把.同时记录体验的过程.如果你也想按照本文的步骤体验的话,那你得先安 ...
- gRPC官方文档(概览)
文章来自gRPC 官方文档中文版 概览 开始 欢迎进入 gRPC 的开发文档,gRPC 一开始由 google 开发,是一款语言中立.平台中立.开源的远程过程调用(RPC)系统. 本文档通过快速概述和 ...
随机推荐
- C++ 洛谷 P1731 [NOI1999]生日蛋糕
P1731 [NOI1999]生日蛋糕 一本通上也有. 这TM是一道极其简单的深搜剪枝(DP当然可以的了,这里我只讲深搜). 首先圆柱公式:(有点数学基础都知道) V=πR2H S侧=π2RH S底= ...
- 1. VMware搭建Linux环境,安装配置centos6.5
1. 安装VMware,后新建虚拟机 2. 为我们的虚拟机挂载操作系统 3.开启我们的虚拟机,为我们的虚拟机进行安装操作系统 4.配置虚拟机连接网络 修改linux的mac地址 修改mac地址配置文件 ...
- 转: windows系统下mysql出现Error 1045(28000) Access Denied for user 'root'@'localhost'
windows系统下mysql出现Error 1045(28000) Access Denied for user 'root'@'localhost' 转自 http://zxy5241.space ...
- .Net Core 学习依赖注入自定义Service
1. 定义一个服务,包含一个方法 public class TextService { public string Print(string m) { return m; } } 2. 写一个扩展方法 ...
- 消息中间件及IBM MQ
MQ 消息中间件: 中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源. 中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯.是连接两个独立应用程 ...
- Spring Cloud 之 Zuul基础.
一.概述 API 网关是一个更为智能的应用服务器,它的定义类似于面向对象设计模式中的 Facade 模式,它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤 ...
- 「PowerBI」Tabular Editor 一个对中文世界很严重的bug即将修复完成
之前介绍过Tabular Editor这款开源工具,对PowerBI建模来说,非常好用,可以极大的增强自动化水平. 详细可查看此文章: 「PowerBI相关」一款极其优秀的DAX建模工具Tabular ...
- Android 常用 Manager的总结
Android 常用 Manager的总结 1 smsManager 发送短信 --使用方法 --SmsManager smsManager = SmsManager.getDe ...
- RabbitMQ延迟消息的延迟极限是多少?
之前在写Spring Cloud Stream专题内容的时候,特地介绍了一下如何使用RabbitMQ的延迟消息来实现定时任务.最近正好因为开发碰到了使用过程中发现,延迟消息没有效果,消息直接就被消费了 ...
- 十、SQL中EXISTS的用法 十三、sql server not exists
十.SQL中EXISTS的用法 EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False EXISTS 指定一个子查询,检测 行 的存在. 语法 ...