[GRPC]GRPC快速上手
概述(Overview)
本文仅记录快速上手的方案 |
GoLand 前置准备
Go Modules配置
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go get google.golang.org/grpc
系统配置
需要手动安装Releases · protocolbuffers/protobuf 至系统 并配置路径到
GoLand插件
C#前置准备
项目配置
插件与包配置
安装 Grpc.Tools 至项目
核心(Core)
GRPC基于一类中间语言规范Proto生成适配各类语言的服务文件 |
文件规范
相关文件需要以.proto结尾
语法规范
Proto关键字 | |
syntax | Proto的语法等级,一般为3 |
package | 包名,会根据不同语言适配 |
option | 命名空间选项,比如C#的命名空间,GO的包名 |
import | 引入其他的Proto文件 |
message | 定义一个类型,比如GO的Stract,C#的Class |
<基元类型> | int,float,string这些。并非C#的基元 |
repeated | 数组类型,或者称为GO的切片类型 |
map | 字典类型,GO的map,C#的Dictionary |
oneof | 用于控制一个片段内只能有一个有值 |
enum | 枚举类型,GO的实现极其本土化 |
Proto案例
- syntax = "proto3";
- package person;
- // GO_Package <包名>;<别名>
- option go_package = "GRPC/pb/person;person";
- import "student.proto";
- message Person{
- // 基元类型
- string name = 1;
- int32 age = 2;
- // bool sex = 3;
- // enum 枚举类型
- enum SEX {
- // 是否允许同Key枚举
- option allow_alias = true;
- MAN = 0;
- WOMAN = 1;
- BOY = 0;
- }
- SEX sex = 3;
- // 切片
- repeated string text = 4;
- // 映射 test_map 会自转换为TestMap
- map <string, string> test_map = 5;
- // 控制片段中只能有一个有值 这个会定义为 Flag
- // 有个函数 isPerson_Falg
- oneof Flag{
- string one = 7;
- string two = 8;
- string three = 9;
- }
- student.Student student = 10;
- // reserved <key>;
- // reserved "test_map"
- // reserved <number>;
- }
- message Home{
- repeated Person persons = 1;
- message V {
- string name = 1;
- }
- V v = 2;
- }
案例(Example)
基于GRPC实现一个简单的计算器。其中GO作为Client,C#作为Server |
GO开发准备
初始项目
安装依赖
- go env -w GO111MODULE=on
- go env -w GOPROXY=https://goproxy.io,direct
- go get google.golang.org/grpc
C#开发准备
初始项目
安装依赖
编写Proto文件
定义请求体CalculateRequest和回应体CalculateResponse,随后定义计算服务CalculateService
- syntax = "proto3";
- package Calculate;
- option go_package = "Calculate.calculate;calculator";
- option csharp_namespace = "CalculatorServer";
- message CalculateRequest {
- float X = 1;
- float Y = 2;
- enum CalculateMethod {
- ADD = 0;
- SUB = 1;
- MUL = 2;
- DIV = 3;
- }
- CalculateMethod Method = 3;
- }
- message CalculateResponse {
- bool Ok = 1;
- float Result = 2;
- string Message = 3;
- }
- service CalculateService{
- rpc BinaryCalculate(CalculateRequest) returns (CalculateResponse);
- }
实现C#服务端
定义一个服务,使其继承自动生成的服务基类,并实现其方法 |
- using Grpc.Core;
- namespace CalculatorServer.Services
- {
- public class CalculatorService: CalculateService.CalculateServiceBase
- {
- public override Task<CalculateResponse> BinaryCalculate(CalculateRequest request, ServerCallContext context)
- {
- float calculateResult = 0.0f;
- switch (request.Method)
- {
- case CalculateRequest.Types.CalculateMethod.Add:
- {
- calculateResult = request.X + request.Y;
- }
- break;
- case CalculateRequest.Types.CalculateMethod.Sub:
- {
- calculateResult = request.X - request.Y;
- }
- break;
- case CalculateRequest.Types.CalculateMethod.Mul:
- {
- calculateResult = request.X * request.Y;
- }
- break;
- case CalculateRequest.Types.CalculateMethod.Div:
- {
- calculateResult = request.X / request.Y;
- }
- break;
- }
- return Task.FromResult(new CalculateResponse { Result = calculateResult,Ok =true,Message = "SUCCESS"});
- }
- }
- }
实现GO客户端
注意GO的相关文件需要手动执行脚本构建一下! |
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative <文件位置>
构建完成后会生成calculate.pb.go和calculate_grpc.pb.go
- package main
- import (
- calculator "Calculator/protoBuffer"
- "context"
- "fmt"
- "google.golang.org/grpc"
- )
- const (
- LocalHost = "localhost:5047"
- HOST = "localhost"
- PORT = ":5047"
- )
- func main() {
- listener, err := grpc.NewClient(LocalHost, grpc.WithInsecure())
- defer func() {
- _ = listener.Close()
- }()
- client := calculator.NewCalculateServiceClient(listener)
- calculateResponse, err := client.BinaryCalculate(context.Background(), &calculator.CalculateRequest{
- X: 10,
- Y: 20,
- Method: calculator.CalculateRequest_MUL,
- })
- if err != nil {
- fmt.Println(err.Error())
- return
- }
- fmt.Println(calculateResponse)
- }