grpc-gateway--支持grpc和restful

The grpc-gateway is a plugin of the Google protocol buffers compiler protoc. It reads protobuf service definitions and generates a reverse-proxy server which 'translates a RESTful HTTP API into gRPC. This server is generated according to the google.api.http annotations in your service definitions.

grpc-gateway是protoc的一个插件。它读取gRPC服务定义,并生成一个反向代理服务器,将RESTful JSON API转换为gRPC。此服务器是根据gRPC定义中的自定义选项生成的。

安装

protoc:https://github.com/protocolbuffers/protobuf/releases

go install \
    github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway \
    github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger \
    github.com/golang/protobuf/protoc-gen-go

简单示例

https://github.com/grpc-ecosystem/grpc-gateway示例项目目录:

.
├── cmd
│   ├── echoclient
│   │   └── client.go
│   ├── echohttp
│   │   └── httpserver.go
│   └── echoserver
│       └── server.go
├── echopb
│   ├── echo.pb.go
│   ├── echo.pb.gw.go
│   ├── echo.proto
│   ├── echo.swagger.json
│   └── google
│       ├── api
│       │   ├── annotations.proto
│       │   ├── httpbody.proto
│       │   └── http.proto
│       └── rpc
│           ├── code.proto
│           ├── error_details.proto
│           └── status.proto
├── go.mod
├── go.sum

echopb/google拷贝自grpc-gateway/third_party。

echo.proto增加 a google.api.http annotation:

syntax = "proto3";
package echopb;

import "google/api/annotations.proto";

message StringMessage{
    string value = 1;
}

service EchoService{
    rpc Echo(StringMessage) returns (StringMessage){
        option (google.api.http) = { 
            post: "/v1/example/echo"
            body: "*" 
        };
    }   
}

echo.pb.go echo.pb.gw.go和echo.swagger.json都是工具生成的。

protoc -I ./echopb/ --go_out=plugins=grpc:echopb echopb/echo.proto
protoc -I echopb --grpc-gateway_out=logtostderr=true:echopb/ echopb/echo.proto
protoc -I echopb/ --swagger_out=logtostderr=true:echopb/ echopb/echo.proto

server.go,监听在localhost:8088

package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    pb "example/echopb" 
)

const (
    port = ":8088"
)

type server struct{
    pb.UnimplementedEchoServiceServer
} 

func (s *server) Echo(ctx context.Context, req *pb.StringMessage) (*pb.StringMessage, error) {
    return &pb.StringMessage{Value: req.GetValue()}, nil 
}

func main(){
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v\n", err)
    }   

    s := grpc.NewServer()
    pb.RegisterEchoServiceServer(s, &server{})

    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }   
}

client.go

package main

import (
    "context"
    "log"
    "time"

    "google.golang.org/grpc"
    pb "example/echopb"
)

const (
    addr = "localhost:8088"
)

func main(){
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()

    conn, err := grpc.DialContext(ctx, addr, grpc.WithBlock(), grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v\n", err)
    }   
    defer conn.Close()
    c := pb.NewEchoServiceClient(conn)

    log.Printf("echo request: wang\n")

    r, err := c.Echo(ctx, &pb.StringMessage{Value: "wang"})
    if err != nil {
        log.Fatalf("could not echo: %v\n", err)
    }   

    log.Printf("Echo reply: %s\n", r.GetValue())
}

httpserver.go

package main

import (
    "context"
    "flag"
    "net/http"

    "github.com/golang/glog"
    "github.com/grpc-ecosystem/grpc-gateway/runtime"
    "google.golang.org/grpc"

    gw "example/echopb"
)

var (
    grpcServerEndpoint = flag.String("grpc-server-endpoint", "localhost:8088", "gRPC server endpoint")
)

func run() error{
    ctx := context.Background()
    ctx, cancel := context.WithCancel(ctx)
    defer cancel()

    mux := runtime.NewServeMux()
    opts := []grpc.DialOption{grpc.WithInsecure()}
    err := gw.RegisterEchoServiceHandlerFromEndpoint(ctx, mux, *grpcServerEndpoint, opts)
    if err != nil {
        return err 
    }   

    return http.ListenAndServe(":8081", mux)
}

func main(){
    flag.Parse()
    defer glog.Flush()

    if err := run(); err != nil {
        glog.Fatal(err)
    }   
}

可通过如下命令本地查看swagger接口:

swagger serve --host=0.0.0.0 --port=9000 --no-open echopb/echo.swagger.json

http://localhost:9000/docs    查看到POST地址: /v1/example/echo

POST: curl -XPOST --data '{"value":"wangqing"}' http://localhost:8081/v1/example/echo

 

openNESS应用

eaa.proto:https://gitee.com/yuxio/specs/blob/master/schema/pb/eaa.proto

syntax = "proto3";

package openness.eaa;
option go_package = "github.com/open-ness/eaa;eaa";

import "google/protobuf/empty.proto";
import "google/api/annotations.proto";
import "protoc-gen-swagger/options/annotations.proto";

生成swagger:

protoc -I./pb -I../../ben-krieger/grpc-gateway -I../../ben-krieger/grpc-gateway/third_party/googleapis --swagger_out=allow_repeated_fields_in_body=true,logtostderr=true:eaa ./pb/eaa.proto

 

参考:

1. https://github.com/grpc-ecosystem/grpc-gateway  https://grpc-ecosystem.github.io/grpc-gateway/

2. grpc-gateway应用 煎鱼  grpc + grpc gateway

3. OpenNESS eaa.proto生成swagger yaml

4. gRPC 调试工具 gRPC-swagger  java版本的调试工具

posted @ 2020-04-19 20:20  yuxi_o  阅读(6608)  评论(0编辑  收藏  举报