Skip to content

Latest commit

 

History

History
146 lines (109 loc) · 3.26 KB

grpc.md

File metadata and controls

146 lines (109 loc) · 3.26 KB

Overview

  1. What is gRPC

Relation to other technologies

  • TODO: more here

Prereq: Protocol Buffers

  1. See protobuf doc

Install

go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

# Verify
ls -al $(go env GOPATH)/bin | grep grpc

which protoc-gen-go-grpc;
find $HOME -name protoc-gen-go-grpc;
  • Ensure protoc-gen-go-grpc is on your $PATH (try to execute directly)
  • May need to add $GOPATH/bin to $PATH (see go env GOPATH)
ln -sv $(go env GOPATH)/bin/protoc-gen-go-grpc $HOME/bin/

Get dependencies

PROJ_ROOT=/dir/containing/go.mod/
cd $PROJ_ROOT

go get google.golang.org/grpc
go mod tidy

Compile

  • see protobuf doc
  • TODO: more here
  • TODO: protoc generates *_grpc.pb.go

Server

  • TODO: embed UnimplementedFoo
  • TODO: implement methods on Foo interface

Construct Objects (eg. for Dependency Injection)

type ListenerAddr string

func NewListenerAddr(defaultPort uint16) ListenerAddr {
    // Google Cloud Run sets this
    port := os.Getenv("PORT")
    if strings.TrimSpace(port) == "" {
        return ListenerAddr(fmt.Sprintf(":%d", defaultPort))
    }

    return ListenerAddr(fmt.Sprintf(":%v", port))
}

func NewListener(addr ListenerAddr) (net.Listener, error) {
    lis, err := net.Listen("tcp", string(addr))
    if err != nil {
        zap.L().Error("failed to listen on address",
            zap.Error(err),
            zap.String("listenAddr", string(addr)),
        )

        return nil, err
    }

    return lis, nil
}

func NewServerOptions(unaryInterceptor grpc.UnaryServerInterceptor) []grpc.ServerOption {
    var opts []grpc.ServerOption

    // TODO: set timeouts here
    // TODO: set buffer sizes here
    // opts = append(opts, grpc.MaxRecvMsgSize(1024*1024*10))

    opts = append(opts, grpc.UnaryInterceptor(unaryInterceptor))
    return opts
}

func NewServer(opts []grpc.ServerOption) *grpc.Server {
    return grpc.NewServer(opts...)
}

func NewService(
    conf *appConf,
    databaseClient *SomeConnection,
) (*service.FooBarService, error) {
    svc := &service.FooBarService{
        UnimplementedAPIServer: api.UnimplementedAPIServer{},
        conn:                   SomeConnection,
        jwtConf:                conf.JWT,
        Clock: func() time.Time {
            return time.Now().UTC()
        },
    }

    err := svc.Validate()
    if err != nil {
        zap.L().Error("failed to validate FooBar service", zap.Error(err))
        return nil, err
    }

    return svc, nil
}

Example main.go

package main

func main() {

    // appObjects.server is a *grpc.Server
    // appObjects.service is a *service.FooBarService (generated by protoc)
    api.RegisterAPIServer(appObjects.server, appObjects.service)

    zap.L().Info("starting grpc server", zap.String("listenAddr", ":8080"))

    // -- blocking
    err = app.server.Serve(appObjects.listener) // appObjects.listener is a net.Listener
    if err != nil {
        zap.L().Error("failed to run server", zap.Error(err))
        os.Exit(20)
    }
}

GZip Compression

  1. Import encoding/gzip package (for side effects)
import _ "google.golang.org/grpc/encoding/gzip"

Other Resources

  1. https://grpc.io/docs/languages/go/basics/