使用Golang中的gRPC和gRPC-Gateway进行集成
发表时间: 2023-12-10 06:54
gRPC: gRPC(gRPC Remote Procedure Calls)是由Google开发的开源RPC(远程过程调用)框架,它使用Protocol Buffers作为接口定义语言。
gRPC特点
gRPC-Gateway: 是一个用于将 gRPC 服务转换为 RESTful JSON API 的代理工具,使得可以通过HTTP/JSON 访问原本基于 gRPC 的服务
gRPC-Gateway特点
buf 是一个用于 Protocol Buffers 的构建和 lint 工具。它提供了一种规范和一致性的方式来管理 Protocol Buffers 文件
syntax = "proto3";//proto的包名package demo;//生成go文件的包名option go_package="/gen;demobp";message Request { string name = 1;}message Response { string message = 1;}service HelloService { rpc SayHello(Request) returns (Response) { }}
version: v1plugins:#插件 - plugin: go #输出到指定当前路径的指定目录 out: gen opt: - paths=source_relative - plugin: go-grpc out: gen opt: - paths=source_relative - plugin: grpc-gateway out: gen opt: - paths=source_relative - generate_unbound_methods=true #gateway要依赖的自定义url的yaml文件 - grpc_api_configuration=demo.yaml
type: google.aip.Serviceconfig_version: 3http:#路由规则 demo.HelloService.SayHello 第一部分demo 这里对应着是 demo.proto文件里定义的包名 package demo; 如果改为package demo1;则selector 也要改成相应的demo1.HelloService.SayHello才可以 ,第二部分HelloService 是服务名,第三部分SayHello 是服务的方法名#参数中的{name} 要和demo.proto中的message中Request中的name相同 rules: - selector: demo.HelloService.SayHello get: /v1/hello/{name} body:"*"
#说明: 如果不加参数,需要与buf.gen.yaml在同一个目录下执行,否则要使用参数指定配置文件才可以buf generate
demo
├── bp
│ ├── buf.gen.yaml
│ ├── demo.proto
│ ├── demo.yaml
│ ├── gen
│ │ ├── demo.pb.go
│ │ ├── demo.pb.gw.go
│ │ └── demo_grpc.pb.go
│ └── genpb.sh
├── client
│ └── main.go
├── go.mod
├── go.sum
├── gw
│ └── main.go
└── server
└── main.go
package mainimport ( bp "bpdemo/bp/gen" "context" "google.golang.org/grpc" "log" "net")type server struct { //必须有,向下兼容的处理 bp.UnimplementedHelloServiceServer}func (s *server) SayHello(ctx context.Context, req *bp.Request) (*bp.Response, error) { return &bp.Response{Message: "Hello " + req.Name}, nil}func main() { lis, err := net.Listen("tcp", ":8080") if err != nil { panic(err) } s := grpc.NewServer() bp.RegisterHelloServiceServer(s, &server{}) if err := s.Serve(lis); err != nil { log.Fatalf("faild to server %v", err) }}
package mainimport ( "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "google.golang.org/grpc" demobp "bpdemo/bp/gen" "context" "fmt" "net/http")func main() { ctx := context.Background() ctx, cancelFunc := context.WithCancel(ctx) defer cancelFunc() //自定义服务 mux := runtime.NewServeMux() err := demobp.RegisterHelloServiceHandlerFromEndpoint(ctx, mux, "127.0.0.1:8080", []grpc.DialOption{grpc.WithInsecure()}) if err != nil { panic(err) } err = http.ListenAndServe(":9090", mux) fmt.Println(err)}
package mainimport ( bp "bpdemo/bp/gen" "context" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "log" "time")func main() { conn, err := grpc.Dial("localhost:8080", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { panic(err) } defer conn.Close() c := bp.NewHelloServiceClient(conn) ctx, cancelFunc := context.WithTimeout(context.Background(), 10*time.Second) defer cancelFunc() r, err := c.SayHello(ctx, &bp.Request{Name: "hello"}) if err != nil { log.Fatalf("get name err: %v", err) } log.Printf("收到内容:%v", r.GetMessage())}