下载包
go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
go get -u github.com/golang/protobuf/protoc-gen-go
go get -u github.com/gogo/protobuf/gogoproto
go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
proto文件
syntax = "proto3";
package api;
import "github.com/gogo/protobuf@v1.3.2/gogoproto/gogo.proto";
import "google/api/annotations.proto";
message String {
string value = 1 [(gogoproto.moretags) = 'form:"value" validate:"required"'];
}
service HelloService {
rpc Hello (String) returns (String){
option (google.api.http) = {
get: "/hello"
};
};
}
生成代码
--grpc-gateway_out=. 表示会生成http的注册函数
--gofast_out 性能更高
protoc -I. -I$GOPATH/src -I$GOPATH/pkg/mod --grpc-gateway_out=. --swagger_out=. --gofast_out=plugins=grpc:. hello.proto
/*
错误日志
protoc -I. -I$GOPATH/src -I$GOPATH/pkg/mod --grpc-gateway_out=. --swagger_out=logtostderr=true:. --gofast_out=plugins=grpc:. api.proto
*/
main函数
func main() {
lis, _ := net.Listen("tcp", ":5000")
grpcServer := grpc.NewServer()
lapi.RegisterHelloServiceServer(grpcServer, new(svc.Service))
mux := runtime.NewServeMux()
_ = lapi.RegisterHelloServiceHandlerFromEndpoint(
context.Background(), mux, "localhost:5000",
[]grpc.DialOption{grpc.WithInsecure()},)
go grpcServer.Serve(lis)
http.ListenAndServe(":8080", mux)
}
业务函数
type Service struct {}
func (svc *Service) Hello(context.Context, *lapi.String) (*lapi.String, error) {
fmt.Println("xcxcvx")
return &lapi.String{Value:"afdaf",}, nil
}
浏览器访问
{"value":"afdaf"}
rpc客户端访问
func helloClient() {
cc, _ := grpc.Dial("localhost:5000", grpc.WithInsecure())
hellServiceCli := lapi.NewHelloServiceClient(cc)
r, _ := hellServiceCli.Hello(context.Background(), &lapi.String{Value: "asdfxxx"})
fmt.Println(r.Value)
}
拦截器
拦截器
func filter(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
fmt.Println("fileter:", info.FullMethod)
fmt.Println("fileter:", info.Server)
fmt.Println("req", req)
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v", r)
}
}()
return handler(ctx, req)
}
//初始化grpcServer时加上拦截器
grpcServer := grpc.NewServer(grpc.UnaryInterceptor(filter))
链式拦截器
import "github.com/grpc-ecosystem/go-grpc-middleware"
grpcServer := grpc.NewServer(
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
filter1, filter2,
)),
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
filter3,
)),
)
使用TLS
生成证书pem文件
openssl genrsa -out privkey.pem 2048
openssl req -new -key privkey.pem -out cert.csr -subj "/CN=localhost/O=myo"
openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095 -subj "/CN=localhost/O=myo"
main.go
package main
import (
"context"
"crypto/tls"
"flag"
"fmt"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"grpcl/api"
svc "grpcl/service"
cert "grpcl/tls"
"log"
"net"
"net/http"
"time"
)
var (
gRPCPort = flag.Int("grpc-port", 10000, "The gRPC server port")
gatewayPort = flag.Int("gateway-port", 11000, "The gRPC-Gateway server port")
)
//客户端测试
func helloClient() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
cc, _ := grpc.DialContext(ctx, net.JoinHostPort("localhost", "10000"),
grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(cert.CertPool, "")),
)
defer cc.Close()
hellServiceCli := api.NewHelloServiceClient(cc)
r, _ := hellServiceCli.Hello(context.Background(), &api.String{Value: "asdfxxx"})
fmt.Println(r.Value)
}
func main() {
flag.Parse()
addr := fmt.Sprintf("localhost:%d", *gRPCPort)
lis, err := net.Listen("tcp", addr)
if err != nil {
log.Fatalln("Failed to listen:", err)
}
s := grpc.NewServer(
grpc.Creds(credentials.NewServerTLSFromCert(&cert.Cert)),
)
api.RegisterHelloServiceServer(s, &svc.Service{})
// Serve gRPC Server
fmt.Println("Serving gRPC on https://", addr)
go func() {
log.Fatal(s.Serve(lis))
}()
conn, err := grpc.DialContext(
context.Background(),
addr,
grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(cert.CertPool, "")),
grpc.WithBlock(),
)
if err != nil {
log.Fatalln("Failed to dial server:", err)
}
gwmux := runtime.NewServeMux()
err = api.RegisterHelloServiceHandler(context.Background(), gwmux, conn)
if err != nil {
log.Fatalln("Failed to register gateway:", err)
}
gatewayAddr := fmt.Sprintf("localhost:%d", *gatewayPort)
fmt.Printf("Serving gRPC-Gateway on https://%s\n", gatewayAddr)
gwServer := http.Server{
Addr: gatewayAddr,
Handler: gwmux,
TLSConfig: &tls.Config{
Certificates: []tls.Certificate{cert.Cert},
},
}
go helloClient()
log.Fatalln(gwServer.ListenAndServeTLS("", ""))
}
cert.go
package cert
import (
"crypto/tls"
"crypto/x509"
"log"
)
var (
// Cert is a self signed certificate
Cert tls.Certificate
// CertPool contains the self signed certificate
CertPool *x509.CertPool
)
func init() {
var err error
Cert, err = tls.LoadX509KeyPair("tls/cacert.pem", "tls/privkey.pem")
if err != nil {
log.Fatalln("Failed to parse key pair:", err)
}
Cert.Leaf, err = x509.ParseCertificate(Cert.Certificate[0])
if err != nil {
log.Fatalln("Failed to parse certificate:", err)
}
CertPool = x509.NewCertPool()
CertPool.AddCert(Cert.Leaf)
}
浏览器访问
https://localhost:11000/hello