GRPC开发(7)-grpc-gateway(同时提供http服务的grpc服务)

这里有grpc环境搭建的完整过程,grpc+grpc-gateway环境搭建

不过如果你是按照这个"GRPC开发"流程看到这里的话,基本环境应该搭建完成了,那就不需要看上面的连接了,我直接给出 grpc-dateway的安装即可

Grpc-gateway安装


cd $GOPATH/src/google.golang.org
git clone https://github.com/google/go-genproto.git
mv go-genproto/ genproto/

//yaml.v2容易下载失败,我们手动下载
cd $GOPATH/src
mkdir gopkg.in
cd gopkg.in
git clone https://github.com/go-yaml/yaml.git
mv yaml yaml.v2

go get -v -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
cd $GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
go build
go install 

gateway使用

然后再进入我们的protoc目录
cd ~/goproject/grpcpro/protoc
新建一个hello.yaml

type: google.api.Service
config_version: 3

http:
  rules:
  - selector: hello.Hello.SayHello
    get: /hello/sayhello
#其中package是hello,service是Hello,方法是SayHello,对外暴露的http get url是 127.0.0.1/hello/sayhello

然后执行命令生成文件

protoc -I/usr/local/include -I. -I$GOPATH/src -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis --go_out=plugins=grpc:. ./hello.proto
protoc -I/usr/local/include -I. -I$GOPATH/src -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis --grpc-gateway_out=logtostderr=true,grpc_api_configuration=./hello.yaml:. ./hello.proto

查看生成的文件

ls
hello.pb.go  hello.pb.gw.go  hello.proto  hello.yaml

其中 hello.pb.gw.go 是新生成的

在server同级创建gateway目录

mkdir -p ~/goproject/grpcpro/gateway
cd ~/goproject/grpcpro/gateway
vim gateway.go

package main

import (
//      "time"
        "log"
        "flag"
        "net/http"
        "google.golang.org/grpc/credentials"
        "crypto/x509"
        "crypto/tls"
        "io/ioutil"
        "github.com/golang/glog"
        gw "grpcpro/protoc"
        "github.com/grpc-ecosystem/grpc-gateway/runtime"
        "golang.org/x/net/context"
        "google.golang.org/grpc"
)

var (
        echoEndpoint = flag.String("echo_endpoint", "localhost:50052", "endpoint of YourService")
)

func main() {


        certificate, err := tls.LoadX509KeyPair("../cert/client.crt", "../cert/client.key")
        if err != nil {
                log.Fatal(err)
        }

        certPool := x509.NewCertPool()
        ca, err := ioutil.ReadFile("../cert/ca.crt")
        if err != nil {
                log.Fatal(err)
        }
        if ok := certPool.AppendCertsFromPEM(ca); !ok {
                log.Fatal("failed to append ca certs")
        }
        creds := credentials.NewTLS(&tls.Config{
                Certificates: []tls.Certificate{certificate},
                ServerName: "grpcpro1", // NOTE: this is required!
                RootCAs: certPool,
        })



        mux := runtime.NewServeMux()
        //ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
        ctx, cancel := context.WithCancel(context.Background())
        defer cancel()
        opts := []grpc.DialOption{grpc.WithTransportCredentials(creds)}
        err = gw.RegisterHelloHandlerFromEndpoint(ctx, mux, *echoEndpoint, opts)
        if err != nil {
                glog.Fatal(err)
        }
        var addr="127.0.0.1:9001"
        if err:=http.ListenAndServeTLS(addr, "../cert/server.crt", "../cert/server.key",mux);err != nil {
        //if err:=http.ListenAndServe(addr,mux);err != nil {
                glog.Fatal(err)
        }

}

然后运行server : cd ~/goproject/grpcpro/server && go run server.go
再运行gateway: cd ~/goproject/grpcpro/gateway &&go run gateway.go

在浏览器访问
https://127.0.0.1:9001/hello/sayhello?name=aa
返回:
{“message”:“Hello aa”}

nginx代理grpc-gateway的http服务

直接追加

 location /hello {
            proxy_pass https://127.0.0.1:9001;
        }

完整内容

server{
        listen 444 default ssl http2;
        #证书(公钥.发送到客户端的)
        ssl_certificate ssl/server.crt;
        #私钥,
        ssl_certificate_key ssl/server.key;
        location /hello.Hello {
            grpc_pass grpcs://backend;
        }
        location /hello {
            proxy_pass https://127.0.0.1:9001;
        }
    }

在浏览器访问
https://127.0.0.1:444/hello/sayhello?name=aa
返回:
{“message”:“Hello aa”}

这样gateway也不需要对外暴露端口,只需要nginx统一代理即可。

到了这里,nginx代理了grpc服务,也代理了http服务。这样,server和gateway都对外不可访问,对内不使用证书可以更快速的开发。。。

安全性,自然是越安全越好。。。

问题

为什么GPRC的RESTFUL API返回结果中忽略默认值或者空值
解决办法
解决办法其实就是把mux.marshalers[”*“]的marshaler的EmitDefaults=true,可以看下这个答案 https://stackoverflow.com/questions/34716238/golang-protobuf-remove-omitempty-tag-from-generated-json-tags 提供的答案就是

gwmux := runtime.NewServeMux(runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{OrigName: true, EmitDefaults: true}))

你可能感兴趣的:(GRPC)