这里有grpc环境搭建的完整过程,grpc+grpc-gateway环境搭建
不过如果你是按照这个"GRPC开发"流程看到这里的话,基本环境应该搭建完成了,那就不需要看上面的连接了,我直接给出 grpc-dateway的安装即可
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
然后再进入我们的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”}
直接追加
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}))