gRPC 环境安装 Mac
由于仓库已经转到 github,命令 go get -u google.golang.org/grpc
已经不能正常工作。
$ brew install libtool
$ brew install automake
# install proto3
$ mkdir tmp
$ cd tmp
$ git clone https://github.com/google/protobuf
$ cd protobuf
$ ./autogen.sh
$ ./configure
$ make
$ make check
$ sudo make install
# install go-grpc, 由于仓库已经转到 github,因此下面命令不能正常工作
# $ go get -u google.golang.org/grpc
$ git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc
$ git clone https://github.com/golang/net.git $GOPATH/src/golang.org/x/net
$ git clone https://github.com/golang/text.git $GOPATH/src/golang.org/x/text
$ git clone https://github.com/google/go-genproto.git $GOPATH/src/google.golang.org/genproto
# $ git clone https://github.com/golang/crypto.git $GOPATH/src/golang.org/x/crypto
# $ git clone https://github.com/golang/sys.git $GOPATH/src/golang.org/x/sys
$ cd $GOPATH/src/ && go install google.golang.org/grpc
$ go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
# go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
# go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
$ go get -u github.com/golang/protobuf/protoc-gen-go
gPRC Interceptors
当前实现的 Interceptors 包括 Auth/Log/Monitor/Trace 等。(auth, logging , trace,message, validation, retries or monitoring),大本营: https://github.com/grpc-ecosystem/go-grpc-middleware
类型两种:
- UnaryInterceptor
- StreamInterceptor
常见拦截器列表如下:
- Go gRPC Middleware: 提供了拦截器的interceptor链式的功能,可以将多个拦截器组合成一个拦截器链,当然它还提供了其它的功能,所以以gRPC中间件命名。
- grpc-multi-interceptor: 是另一个interceptor链式功能的库,也可以将单向的或者流式的拦截器组合。
- grpc_auth: 身份验证拦截器
- grpc_ctxtags: 为上下文增加
Tag
map对象 - grpc_zap: 支持
zap
日志框架 - grpc_logrus: 支持
logrus
日志框架 - grpc_prometheus: 支持
prometheus
- otgrpc: 支持opentracing/zipkin
- grpc_opentracing:支持opentracing/zipkin
- grpc_retry: 为客户端增加重试的功能
- grpc_validator: 为服务器端增加校验的功能
- xrequestid: 将request id 设置到context中
- go-grpc-interceptor: 解析
Accept-Language
并设置到context - requestdump: 输出request/response
Prometheus 样例如下:
添加了 Zipkin 与 Logger 的代码样例:
client
package main
import (
"log"
"os"
"time"
"golang.org/x/net/context"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
const (
address = "localhost:50051"
defaultName = "world"
)
func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBalancerName())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Message)
}
server.go
package main
import (
"log"
"net"
"golang.org/x/net/context"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
"google.golang.org/grpc/reflection"
"github.com/sirupsen/logrus"
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
"github.com/grpc-ecosystem/go-grpc-middleware"
"github.com/grpc-ecosystem/go-grpc-middleware/tags"
"github.com/opentracing/opentracing-go"
zipkin "github.com/openzipkin-contrib/zipkin-go-opentracing"
"fmt"
"os"
"github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
)
const (
port = ":50051"
)
// server is used to implement helloworld.GreeterServer.
type server struct{}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
var (
logrusLogger *logrus.Logger
customFunc grpc_logrus.CodeToLevel
)
func init(){
// docker run -d -p 9411:9411 -p 9410:9410 openzipkin/zipkin
// create collector.
collector, err := zipkin.NewHTTPCollector("http://localhost:9411/api/v1/spans")
if err != nil {
fmt.Printf("unable to create Zipkin HTTP collector: %+v\n", err)
os.Exit(-1)
}
// create recorder.
recorder := zipkin.NewRecorder(collector, false, "127.0.0.1:50051", "greeter_server")
// create tracer.
tracer, err := zipkin.NewTracer(
recorder,
zipkin.ClientServerSameSpan(true),
zipkin.TraceID128Bit(true),
)
if err != nil {
fmt.Printf("unable to create Zipkin tracer: %+v\n", err)
os.Exit(-1)
}
// explicitly set our tracer to be the default tracer.
opentracing.InitGlobalTracer(tracer)
}
func main() {
// Logrus entry is used, allowing pre-definition of certain fields by the user.
logrusLogger = logrus.New()
logrusLogger.SetFormatter(&logrus.JSONFormatter{})
logrusEntry := logrus.NewEntry(logrusLogger)
// Shared options for the logger, with a custom gRPC code to log level function.
customFunc = grpc_logrus.DefaultCodeToLevel
opts := []grpc_logrus.Option{
grpc_logrus.WithLevels(customFunc),
}
// Shared options for the logger, with a custom duration to log field function.
//opts := []grpc_logrus.Option{
// grpc_logrus.WithDurationField(func(duration time.Duration) (key string, value interface{}) {
// return "grpc.time_ns", duration.Nanoseconds()
// }),
//}
// Make sure that log statements internal to gRPC library are logged using the logrus Logger as well.
grpc_logrus.ReplaceGrpcLogger(logrusEntry)
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
// Create a server, make sure we put the grpc_ctxtags context before everything else.
s := grpc.NewServer(
grpc_middleware.WithUnaryServerChain(
grpc_ctxtags.UnaryServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
grpc_logrus.UnaryServerInterceptor(logrusEntry, opts...),
grpc_opentracing.UnaryServerInterceptor(),
),
grpc_middleware.WithStreamServerChain(
grpc_ctxtags.StreamServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
grpc_logrus.StreamServerInterceptor(logrusEntry, opts...),
grpc_opentracing.StreamServerInterceptor(),
),
)
// s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
// Register reflection service on gRPC server.
reflection.Register(s)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
server 端的产奖配置可以如下:
import "github.com/grpc-ecosystem/go-grpc-middleware"
myServer := grpc.NewServer(
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
grpc_ctxtags.StreamServerInterceptor(),
grpc_opentracing.StreamServerInterceptor(),
grpc_prometheus.StreamServerInterceptor,
grpc_zap.StreamServerInterceptor(zapLogger),
grpc_auth.StreamServerInterceptor(myAuthFunction),
grpc_recovery.StreamServerInterceptor(),
)),
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
grpc_ctxtags.UnaryServerInterceptor(),
grpc_opentracing.UnaryServerInterceptor(),
grpc_prometheus.UnaryServerInterceptor,
grpc_zap.UnaryServerInterceptor(zapLogger),
grpc_auth.UnaryServerInterceptor(myAuthFunction),
grpc_recovery.UnaryServerInterceptor(),
)),
)
分类如下:
Auth
grpc_auth
– a customizable (viaAuthFunc
) piece of auth middleware
Logging
grpc_ctxtags
– a library that adds aTag
map to context, with data populated from request bodygrpc_zap
– integration of zap logging library into gRPC handlers.grpc_logrus
– integration of logrus logging library into gRPC handlers.
Monitoring
grpc_prometheus
⚡ – Prometheus client-side and server-side monitoring middlewareotgrpc
⚡ – OpenTracing client-side and server-side interceptorsgrpc_opentracing
– OpenTracing client-side and server-side interceptors with support for streaming and handler-returned tags
Client
grpc_retry
– a generic gRPC response code retry mechanism, client-side middleware
Server
grpc_validator
– codegen inbound message validation from.proto
optionsgrpc_recovery
– turn panics into gRPC errors