grpc: avoid allocations for each message (#11)

* grpc: avoid allocations for each message
* fix tests for api/router

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2020-08-20 14:45:47 +03:00 committed by GitHub
parent 5ea2590891
commit 98ba3b2788
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 30 deletions

View File

@ -15,6 +15,8 @@ import (
"github.com/unistack-org/micro/v3/api/router" "github.com/unistack-org/micro/v3/api/router"
rregistry "github.com/unistack-org/micro/v3/api/router/registry" rregistry "github.com/unistack-org/micro/v3/api/router/registry"
rstatic "github.com/unistack-org/micro/v3/api/router/static" rstatic "github.com/unistack-org/micro/v3/api/router/static"
"github.com/unistack-org/micro/v3/broker"
bmemory "github.com/unistack-org/micro/v3/broker/memory"
"github.com/unistack-org/micro/v3/client" "github.com/unistack-org/micro/v3/client"
gcli "github.com/unistack-org/micro/v3/client/grpc" gcli "github.com/unistack-org/micro/v3/client/grpc"
rmemory "github.com/unistack-org/micro/v3/registry/memory" rmemory "github.com/unistack-org/micro/v3/registry/memory"
@ -50,10 +52,12 @@ func (s *testServer) CallPcreInvalid(ctx context.Context, req *pb.Request, rsp *
func initial(t *testing.T) (server.Server, client.Client) { func initial(t *testing.T) (server.Server, client.Client) {
r := rmemory.NewRegistry() r := rmemory.NewRegistry()
b := bmemory.NewBroker(broker.Registry(r))
// create a new client // create a new client
s := gsrv.NewServer( s := gsrv.NewServer(
server.Name("foo"), server.Name("foo"),
server.Broker(b),
server.Registry(r), server.Registry(r),
) )
@ -64,6 +68,7 @@ func initial(t *testing.T) (server.Server, client.Client) {
// create a new server // create a new server
c := gcli.NewClient( c := gcli.NewClient(
client.Router(rtr), client.Router(rtr),
client.Broker(b),
) )
h := &testServer{} h := &testServer{}

View File

@ -8,6 +8,7 @@ import (
"net" "net"
"reflect" "reflect"
"strings" "strings"
"sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -24,9 +25,11 @@ import (
) )
type grpcClient struct { type grpcClient struct {
opts client.Options opts client.Options
pool *pool codecs map[string]encoding.Codec
once atomic.Value pool *pool
once atomic.Value
sync.RWMutex
} }
func init() { func init() {
@ -301,18 +304,13 @@ func (g *grpcClient) maxSendMsgSizeValue() int {
} }
func (g *grpcClient) newGRPCCodec(contentType string) (encoding.Codec, error) { func (g *grpcClient) newGRPCCodec(contentType string) (encoding.Codec, error) {
codecs := make(map[string]encoding.Codec) g.RLock()
if g.opts.Context != nil { defer g.RUnlock()
if v := g.opts.Context.Value(codecsKey{}); v != nil {
codecs = v.(map[string]encoding.Codec) if c, ok := g.codecs[contentType]; ok {
}
}
if c, ok := codecs[contentType]; ok {
return wrapCodec{c}, nil
}
if c, ok := defaultGRPCCodecs[contentType]; ok {
return wrapCodec{c}, nil return wrapCodec{c}, nil
} }
return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType)
} }
@ -721,6 +719,22 @@ func newClient(opts ...client.Option) client.Client {
c = options.Wrappers[i-1](c) c = options.Wrappers[i-1](c)
} }
rc.codecs = make(map[string]encoding.Codec, len(defaultGRPCCodecs))
for k, v := range defaultGRPCCodecs {
rc.codecs[k] = v
}
var codecs map[string]encoding.Codec
if rc.opts.Context != nil {
if v := rc.opts.Context.Value(codecsKey{}); v != nil {
codecs = v.(map[string]encoding.Codec)
}
}
for k, v := range codecs {
rc.codecs[k] = v
}
return c return c
} }

View File

@ -64,6 +64,8 @@ type grpcServer struct {
// registry service instance // registry service instance
rsvc *registry.Service rsvc *registry.Service
codecs map[string]encoding.Codec
} }
func init() { func init() {
@ -73,22 +75,19 @@ func init() {
} }
func newGRPCServer(opts ...server.Option) server.Server { func newGRPCServer(opts ...server.Option) server.Server {
options := newOptions(opts...)
// create a grpc server // create a grpc server
srv := &grpcServer{ srv := &grpcServer{
opts: options, opts: server.Options{},
rpc: &rServer{ rpc: &rServer{
serviceMap: make(map[string]*service), serviceMap: make(map[string]*service),
}, },
handlers: make(map[string]server.Handler), handlers: make(map[string]server.Handler),
subscribers: make(map[*subscriber][]broker.Subscriber), subscribers: make(map[*subscriber][]broker.Subscriber),
exit: make(chan chan error), exit: make(chan chan error),
wg: wait(options.Context),
} }
// configure the grpc server // configure the grpc server
srv.configure() srv.configure(opts...)
return srv return srv
} }
@ -110,8 +109,8 @@ func (g *grpcServer) configure(opts ...server.Option) {
g.Lock() g.Lock()
defer g.Unlock() defer g.Unlock()
// Don't reprocess where there's no config // Don't reprocess if server created
if len(opts) == 0 && g.srv != nil { if g.srv != nil {
return return
} }
@ -121,6 +120,22 @@ func (g *grpcServer) configure(opts ...server.Option) {
g.wg = wait(g.opts.Context) g.wg = wait(g.opts.Context)
g.codecs = make(map[string]encoding.Codec, len(defaultGRPCCodecs))
for k, v := range defaultGRPCCodecs {
g.codecs[k] = v
}
var codecs map[string]encoding.Codec
if g.opts.Context != nil {
if v, ok := g.opts.Context.Value(codecsKey{}).(map[string]encoding.Codec); ok && v != nil {
codecs = v
}
}
for k, v := range codecs {
g.codecs[k] = v
}
maxMsgSize := g.getMaxMsgSize() maxMsgSize := g.getMaxMsgSize()
gopts := []grpc.ServerOption{ gopts := []grpc.ServerOption{
@ -519,18 +534,13 @@ func (g *grpcServer) processStream(stream grpc.ServerStream, service *service, m
} }
func (g *grpcServer) newGRPCCodec(contentType string) (encoding.Codec, error) { func (g *grpcServer) newGRPCCodec(contentType string) (encoding.Codec, error) {
codecs := make(map[string]encoding.Codec) g.RLock()
if g.opts.Context != nil { defer g.RUnlock()
if v, ok := g.opts.Context.Value(codecsKey{}).(map[string]encoding.Codec); ok && v != nil {
codecs = v if c, ok := g.codecs[contentType]; ok {
}
}
if c, ok := codecs[contentType]; ok {
return c, nil
}
if c, ok := defaultGRPCCodecs[contentType]; ok {
return c, nil return c, nil
} }
return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType)
} }