说到gRPC就不得不提RPC,所谓RPC(remote procedure call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,简单点来说就是我A机器上写的函数可以在B机器上通过RPC协议直接调用。
它与http不同的是:
为什么内部(约定情况下的服务与服务)使用rpc,而外部(to customer)使用http
gRPC
是一个高性能、开源的通用RPC
框架,最初是由谷歌创建的,十多年来谷歌一直使用一个称为Stubby
的通用RPC
基础设施来连接在其数据中心内和跨数据中心运行的大量微服务。2015年3月,Google
决定构建下一个版本的Stubby
并使其开源。结果就是 gRPC
,它现在被谷歌以外的许多组织用于支持从微服务到“最后一英里”计算(移动、网络和物联网)的用例。
gRPC官方文档:https://www.grpc.io/docs/what-is-grpc/
在 gRPC 中,客户端应用程序可以直接调用不同机器上的服务器应用程序上的方法,就像它是本地对象一样,使您可以更轻松地创建分布式应用程序和服务。与许多 RPC 系统一样,gRPC 基于定义服务的思想,指定可以通过参数和返回类型远程调用的方法。在服务器端,服务器实现了这个接口并运行一个 gRPC 服务器来处理客户端调用。在客户端,客户端有一个存根(在某些语言中简称为客户端),它提供与服务器相同的方法。
Goland详细步骤安装:https://blog.csdn.net/u014374975/article/details/120387180
Golang语法详解请:https://blog.csdn.net/u014374975/article/details/120463448
可以通过Go、C++、C#、Java、Python等语言轻松的创建gRPC服务,同时也意味着它可以跨语言进行远程过程调用,那么就需要一门中间语言(IDL)来约束和定义远程过程调用之间通讯的接口约束。Google官方推荐并且使用人数最多的就是Protocol Buffer
,它具有稍微简化的语法,一些有用的新功能,并支持更多语言。Proto3 目前可用于 Java、C++、Dart、Python、Objective-C、C#等
Protocol Buffer官方文档:https://developers.google.com/protocol-buffers
在GitHub的protocolbuffers项目下,下载ProtocalBuffer编译器
将下载好的Protocal Buffer压缩包解压,并将运行目录配置到环境变量
环境变量添加完毕后,打开cmd
窗口执行protoc --version
,出现版本号,表示配置成功
protoc-gen-go是protobuf编译插件系列中的Go版本,protoc-gen-go可以将Protocol Buffer写的接口定义转换封装为Golang代码
在下载protoc-gen-go之前,我们先设置下Golang代理地址
# 七牛云 go env -w GOPROXY=https://goproxy.cn,direct
go get -u github.com/golang/protobuf/protoc-gen-go
如果GOPATH的bin目录下有这个文件即表示下载成功
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2TCBYJOO-1633354844949)(FDAE29AC35E14B0E87E0DBE7A84CAAF1)]
打开IDE,在GOPATH的src目录下创建一个pbfiles
文件夹,并在文件夹中添加一个product.proto
文件,用于描述接口定义
syntax = "proto3"; package pbfiles; option go_package = "../services"; message Product{ int32 id = 1; string name = 2; int32 count = 3; string description = 4; } service pdService{ rpc GetProduct(Product) returns(Product); }
添加完成后,通过protoc
编译该文件为Golang代码
protoc --go_out=plugins=grpc:./ *.proto
此时我们发现,protoc会在src目录下自动创建一个services
目录,并将上面写的proto
文件自动编译为product.pb.go
由于编译出的Golang代码使用了google.golang.org
等包,所以我们添加一个mod
文件,拉取缺少的模块。
进入src目录执行go mod init gRPCdemo
命令
创建完毕后输入命令go mod tidy
,此时上面生成的product.pb.go
代码就不会缺少引用和标红了
在src目录下创建grpc-server.go
文件,并输入代码:
package main import ( "context" "fmt" "gRPCdemo/services" "google.golang.org/grpc" "net" ) type productRequest struct { } func (this *productRequest) GetProduct(context context.Context, request *services.Product) (*services.Product, error) { var product services.Product switch request.Id { case 1: product.Id = 1 product.Name = "苹果" product.Description = "小苹果" case 2: product.Id = 1 product.Name = "西瓜" product.Description = "大西瓜" default: product.Id = 3 product.Name = "香蕉" product.Description = "香蕉" } return &product, nil } func main() { grpcService := grpc.NewServer() services.RegisterPdServiceServer(grpcService, new(productRequest)) listen, err := net.Listen("tcp", ":5000") if err != nil { fmt.Println("listen err:", err) return } grpcService.Serve(listen) }
在代码目录下打开终端输入go run grpc-server.go
运行程序,开始监听
在src目录下创建grpc-client.go
文件,并输入代码:
package main import ( "context" "fmt" "gRPCdemo/services" "google.golang.org/grpc" ) func main() { grpcCnn, err := grpc.Dial(":5000", grpc.WithInsecure()) if err != nil { fmt.Println("grpc.dial err:", err) return } grpcClient := services.NewPdServiceClient(grpcCnn) var request services.Product request.Id = 1 res, err := grpcClient.GetProduct(context.TODO(), &request) if err != nil { fmt.Println("GetProduct err:", err) return } fmt.Println(res) }
在代码目录下打开终端输入go run grpc-client.go
运行程序
此时可以看到,已成功访问gRPC服务
grpcClient
管理Nuget程序包
,添加如下包Protos
文件夹product.proto
文件中的命名空间更新为.NetCore项目的命名空间:syntax = "proto3"; package pbfiles; option csharp_namespace = "grpcClient"; message Product{ int32 id = 1; string name = 2; int32 count = 3; string description = 4; } service pdService{ rpc GetProduct(Product) returns(Product); }
grpcClient.csproj
项目文件greet.proto
文件的<Protobuf>
元素的项组:<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp3.1</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Google.Protobuf" Version="3.18.0" /> <PackageReference Include="Grpc.Net.Client" Version="2.39.0" /> <PackageReference Include="Grpc.Tools" Version="2.41.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> <!--添加Protobuf元素组--> <Protobuf Include="Protos\product.proto" GrpcServices="Client" /> </ItemGroup> </Project>
grpcClient
命名空间中创建类型。GrpcGreeter
类型是由生成进程自动生成的。grpcClient
客户端的 Program.cs 文件:using Grpc.Net.Client; using System; namespace grpcClient { class Program { static void Main(string[] args) { // 只有 .NET Core 3.x 需要 System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport 开关。 .NET 5 中不需要任何额外配置,也没有这项要求。 AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); using var channel = GrpcChannel.ForAddress("http://localhost:5000"); var client = new pdService.pdServiceClient(channel); var reply = client.GetProduct(new Product { Id = 1 }); Console.WriteLine(reply); Console.ReadKey(); } } }
启动程序后,.NetCore完美访问Golang搭建的gRPC服务
gRPC官方文档:https://www.grpc.io/docs/what-is-grpc/
Protocol Buffer官方文档:https://developers.google.com/protocol-buffers
MSDN:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/grpc/grpc-start?view=aspnetcore-5.0&tabs=visual-studio