Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
1,000 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package grpc | ||
|
||
import ( | ||
"github.com/micro/go-micro/v3/client" | ||
gclient "github.com/micro/go-micro/v3/client/grpc" | ||
"github.com/micro/go-micro/v3/model" | ||
"github.com/micro/go-micro/v3/server" | ||
gserver "github.com/micro/go-micro/v3/server/grpc" | ||
"github.com/micro/go-micro/v3/service" | ||
) | ||
|
||
type grpcService struct { | ||
opts service.Options | ||
} | ||
|
||
func newService(opts ...service.Option) service.Service { | ||
options := service.NewOptions(opts...) | ||
|
||
return &grpcService{ | ||
opts: options, | ||
} | ||
} | ||
|
||
func (s *grpcService) Name() string { | ||
return s.opts.Server.Options().Name | ||
} | ||
|
||
// Init initialises options. Additionally it calls cmd.Init | ||
// which parses command line flags. cmd.Init is only called | ||
// on first Init. | ||
func (s *grpcService) Init(opts ...service.Option) { | ||
// process options | ||
for _, o := range opts { | ||
o(&s.opts) | ||
} | ||
} | ||
|
||
func (s *grpcService) Options() service.Options { | ||
return s.opts | ||
} | ||
|
||
func (s *grpcService) Client() client.Client { | ||
return s.opts.Client | ||
} | ||
|
||
func (s *grpcService) Server() server.Server { | ||
return s.opts.Server | ||
} | ||
|
||
func (s *grpcService) Model() model.Model { | ||
return s.opts.Model | ||
} | ||
|
||
func (s *grpcService) String() string { | ||
return "grpc" | ||
} | ||
|
||
func (s *grpcService) Start() error { | ||
for _, fn := range s.opts.BeforeStart { | ||
if err := fn(); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
if err := s.opts.Server.Start(); err != nil { | ||
return err | ||
} | ||
|
||
for _, fn := range s.opts.AfterStart { | ||
if err := fn(); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (s *grpcService) Stop() error { | ||
var gerr error | ||
|
||
for _, fn := range s.opts.BeforeStop { | ||
if err := fn(); err != nil { | ||
gerr = err | ||
} | ||
} | ||
|
||
if err := s.opts.Server.Stop(); err != nil { | ||
return err | ||
} | ||
|
||
for _, fn := range s.opts.AfterStop { | ||
if err := fn(); err != nil { | ||
gerr = err | ||
} | ||
} | ||
|
||
return gerr | ||
} | ||
|
||
func (s *grpcService) Run() error { | ||
if err := s.Start(); err != nil { | ||
return err | ||
} | ||
|
||
// wait on context cancel | ||
<-s.opts.Context.Done() | ||
|
||
return s.Stop() | ||
} | ||
|
||
// NewService returns a grpc service compatible with go-micro.Service | ||
func NewService(opts ...service.Option) service.Service { | ||
// our grpc client | ||
c := gclient.NewClient() | ||
// our grpc server | ||
s := gserver.NewServer() | ||
|
||
// create options with priority for our opts | ||
options := []service.Option{ | ||
service.Client(c), | ||
service.Server(s), | ||
} | ||
|
||
// append passed in opts | ||
options = append(options, opts...) | ||
|
||
// generate and return a service | ||
return newService(options...) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
package grpc | ||
|
||
import ( | ||
"context" | ||
"crypto/tls" | ||
"sync" | ||
"testing" | ||
"time" | ||
|
||
"github.com/micro/go-micro/v3/registry/memory" | ||
"github.com/micro/go-micro/v3/service" | ||
hello "github.com/micro/go-micro/v3/service/grpc/proto" | ||
mls "github.com/micro/go-micro/v3/util/tls" | ||
) | ||
|
||
type testHandler struct{} | ||
|
||
func (t *testHandler) Call(ctx context.Context, req *hello.Request, rsp *hello.Response) error { | ||
rsp.Msg = "Hello " + req.Name | ||
return nil | ||
} | ||
|
||
func TestGRPCService(t *testing.T) { | ||
var wg sync.WaitGroup | ||
wg.Add(1) | ||
|
||
ctx, cancel := context.WithCancel(context.Background()) | ||
defer cancel() | ||
|
||
// create memory registry | ||
r := memory.NewRegistry() | ||
|
||
// create GRPC service | ||
service := NewService( | ||
service.Name("test.service"), | ||
service.Registry(r), | ||
service.AfterStart(func() error { | ||
wg.Done() | ||
return nil | ||
}), | ||
service.Context(ctx), | ||
) | ||
|
||
// register test handler | ||
hello.RegisterTestHandler(service.Server(), &testHandler{}) | ||
|
||
// run service | ||
errCh := make(chan error, 1) | ||
go func() { | ||
defer close(errCh) | ||
errCh <- service.Run() | ||
}() | ||
|
||
// wait for start | ||
wg.Wait() | ||
|
||
// create client | ||
test := hello.NewTestService("test.service", service.Client()) | ||
|
||
// call service | ||
ctx2, cancel2 := context.WithTimeout(context.Background(), time.Duration(time.Second)) | ||
defer cancel2() | ||
rsp, err := test.Call(ctx2, &hello.Request{ | ||
Name: "John", | ||
}) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// check server | ||
select { | ||
case err := <-errCh: | ||
t.Fatal(err) | ||
case <-time.After(time.Second): | ||
break | ||
} | ||
|
||
// check message | ||
if rsp.Msg != "Hello John" { | ||
t.Fatalf("unexpected response %s", rsp.Msg) | ||
} | ||
} | ||
|
||
func TestGRPCTLSService(t *testing.T) { | ||
var wg sync.WaitGroup | ||
wg.Add(1) | ||
|
||
ctx, cancel := context.WithCancel(context.Background()) | ||
defer cancel() | ||
|
||
// create memory registry | ||
r := memory.NewRegistry() | ||
|
||
// create cert | ||
cert, err := mls.Certificate("test.service") | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
config := &tls.Config{ | ||
Certificates: []tls.Certificate{cert}, | ||
InsecureSkipVerify: true, | ||
} | ||
|
||
// create GRPC service | ||
service := NewService( | ||
service.Name("test.service"), | ||
service.Registry(r), | ||
service.AfterStart(func() error { | ||
wg.Done() | ||
return nil | ||
}), | ||
service.Context(ctx), | ||
// set TLS config | ||
WithTLS(config), | ||
) | ||
|
||
// register test handler | ||
hello.RegisterTestHandler(service.Server(), &testHandler{}) | ||
|
||
// run service | ||
errCh := make(chan error, 1) | ||
go func() { | ||
defer close(errCh) | ||
errCh <- service.Run() | ||
}() | ||
|
||
// wait for start | ||
wg.Wait() | ||
|
||
// create client | ||
test := hello.NewTestService("test.service", service.Client()) | ||
|
||
// call service | ||
ctx2, cancel2 := context.WithTimeout(context.Background(), time.Duration(time.Second)) | ||
defer cancel2() | ||
rsp, err := test.Call(ctx2, &hello.Request{ | ||
Name: "John", | ||
}) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// check server | ||
select { | ||
case err := <-errCh: | ||
t.Fatal(err) | ||
case <-time.After(time.Second): | ||
break | ||
} | ||
|
||
// check message | ||
if rsp.Msg != "Hello John" { | ||
t.Fatalf("unexpected response %s", rsp.Msg) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package grpc | ||
|
||
import ( | ||
"crypto/tls" | ||
|
||
gc "github.com/micro/go-micro/v3/client/grpc" | ||
gs "github.com/micro/go-micro/v3/server/grpc" | ||
"github.com/micro/go-micro/v3/service" | ||
) | ||
|
||
// WithTLS sets the TLS config for the service | ||
func WithTLS(t *tls.Config) service.Option { | ||
return func(o *service.Options) { | ||
o.Client.Init( | ||
gc.AuthTLS(t), | ||
) | ||
o.Server.Init( | ||
gs.AuthTLS(t), | ||
) | ||
} | ||
} |
Oops, something went wrong.