搭建grpc环境 前情提要 我这个demo是在mac(intel)环境实现的,windows和linux大同小异,可自行在网上搜索。
环境依赖
go 1 2 3 4 brew install go go version go version go1.17 darwin/amd64
buf buf 其实是一种protobuf编译器,相比入传统的protoc命令行方式,buf以配置文件的方式更加方便明了。buf又有以下几个优势:
1 2 3 4 5 6 BIN="/usr/local/bin" && \ VERSION="1.4.0" && \ curl -sSL \ "https://github.com/bufbuild/buf/releases/download/v${VERSION} /buf-$(uname -s) -$(uname -m) " \ -o "${BIN} /buf" && \ chmod +x "${BIN} /buf"
官网参考
开始
在你的工作目录创建一个文件夹用于存放项目
创建以下目录结构
1 2 3 4 example_grpc - api - cmd - pkg
初始化项目
1 2 go mod init example_grpc go mod tidy
在api/下创建api.proto文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 syntax = "proto3" ; package api;option go_package = "/api" ; service Example { rpc Ping(PingRequest) returns (PingResponse) {} } message PingRequest {} message PingResponse { int32 Code = 10 ; string Msg = 20 ; }
在项目根目录下创建以下buf配置文件:
1 2 3 4 5 6 version: v1beta1 name: buf.build/adjutant/grpc_example deps: - buf.build/beta/googleapis - buf.build/grpc-ecosystem/grpc-gateway
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 version: v1beta1 plugins: - name: go out: . opt: - paths=source_relative - name: go-grpc out: . opt: - paths=source_relative - require_unimplemented_servers=false - name: grpc-gateway out: . opt: - paths=source_relative - grpc_api_configuration=gw_mapping.yaml - name: openapiv2 out: . opt: - grpc_api_configuration=gw_mapping.yaml
gw.mapping.yaml
grpc方法和http接口路由配置
1 2 3 4 5 6 7 8 type: google.api.Service config_version: 3 http: rules: - selector: api.Example.Ping get: /ping
安装go插件 1 2 3 4 5 go install \ github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway \ github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 \ google.golang.org/protobuf/cmd/protoc-gen-go \ google.golang.org/grpc/cmd/protoc-gen-go-grpc
编译proto文件 1 2 buf mod update buf generate
执行上面两条命令之后,得到以下文件
1 2 3 4 5 - api/ - api.pb.go - api.gw.pb.go - api.pb.go - api.swagger.json
注册服务 注册 在cmd/下创建main.go文件,内容为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 package mainimport ( "context" "example_grpc/api" "example_grpc/pkg/handler" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "log" "net" "net/http" ) const ( grpcServerEndpoint = "127.0.0.1:9091" ) func main () { go toGRPC() go toHTTP() select {} } func toGRPC () { s := grpc.NewServer() api.RegisterExampleServer(s, &handler.Handler{}) lis, err := net.Listen("tcp" , grpcServerEndpoint) if err != nil { log.Panicf("net.Listen err: %+v" , err) } if err := s.Serve(lis); err != nil { log.Panicf("s.Server err: %+v" , err) } } func toHTTP () { ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() mux := runtime.NewServeMux() opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())} err := api.RegisterExampleHandlerFromEndpoint(ctx, mux, grpcServerEndpoint, opts) if err != nil { log.Panicf("RegisterLabHandlerFromEndpoint err: %+v" , err) } if err := http.ListenAndServe(":8082" , mux); err != nil { log.Panicf("ListenAndServe err: %+v" , err) } }
在pkg/api/下创建ping.go文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package handlerimport ( "context" "example_grpc/api" ) type Handler struct {}func (Handler) Ping(ctx context.Context, request *api.PingRequest) (*api.PingResponse, error ) { resp := &api.PingResponse{ Code: 0 , Msg: "ok" , } return resp, nil }
测试 1 2 curl --location --request GET 'http://127.0.0.1:8082/ping' {"Code" :0,"Msg" :"ok" }