1
0
mirror of https://github.com/go-micro/go-micro.git synced 2025-06-12 22:07:47 +02:00

The mega cruft proxy PR (#974)

* the mega cruft proxy PR

* Rename broker id

* add protocol=grpc

* fix compilation breaks

* Add the tunnel broker to the network

* fix broker id

* continue to be backwards compatible in the protocol
This commit is contained in:
Asim Aslam
2019-11-25 16:31:43 +00:00
committed by GitHub
parent 252667398e
commit 080363e8c4
23 changed files with 595 additions and 196 deletions

View File

@ -14,6 +14,7 @@ import (
"github.com/micro/go-micro/broker"
"github.com/micro/go-micro/codec"
raw "github.com/micro/go-micro/codec/bytes"
"github.com/micro/go-micro/metadata"
"github.com/micro/go-micro/registry"
"github.com/micro/go-micro/transport"
@ -30,11 +31,13 @@ type rpcServer struct {
sync.RWMutex
opts Options
handlers map[string]Handler
subscribers map[*subscriber][]broker.Subscriber
subscribers map[Subscriber][]broker.Subscriber
// marks the serve as started
started bool
// used for first registration
registered bool
// subscribe to service name
subscriber broker.Subscriber
// graceful exit
wg *sync.WaitGroup
}
@ -43,12 +46,13 @@ func newRpcServer(opts ...Option) Server {
options := newOptions(opts...)
router := newRpcRouter()
router.hdlrWrappers = options.HdlrWrappers
router.subWrappers = options.SubWrappers
return &rpcServer{
opts: options,
router: router,
handlers: make(map[string]Handler),
subscribers: make(map[*subscriber][]broker.Subscriber),
subscribers: make(map[Subscriber][]broker.Subscriber),
exit: make(chan chan error),
wg: wait(options.Context),
}
@ -56,12 +60,85 @@ func newRpcServer(opts ...Option) Server {
type rpcRouter struct {
h func(context.Context, Request, interface{}) error
m func(context.Context, Message) error
}
func (r rpcRouter) ProcessMessage(ctx context.Context, msg Message) error {
return r.m(ctx, msg)
}
func (r rpcRouter) ServeRequest(ctx context.Context, req Request, rsp Response) error {
return r.h(ctx, req, rsp)
}
// HandleEvent handles inbound messages to the service directly
// TODO: handle requests from an event. We won't send a response.
func (s *rpcServer) HandleEvent(e broker.Event) error {
// formatting horrible cruft
msg := e.Message()
if msg.Header == nil {
// create empty map in case of headers empty to avoid panic later
msg.Header = make(map[string]string)
}
// get codec
ct := msg.Header["Content-Type"]
// default content type
if len(ct) == 0 {
msg.Header["Content-Type"] = DefaultContentType
ct = DefaultContentType
}
// get codec
cf, err := s.newCodec(ct)
if err != nil {
return err
}
// copy headers
hdr := make(map[string]string)
for k, v := range msg.Header {
hdr[k] = v
}
// create context
ctx := metadata.NewContext(context.Background(), hdr)
// TODO: inspect message header
// Micro-Service means a request
// Micro-Topic means a message
rpcMsg := &rpcMessage{
topic: msg.Header["Micro-Topic"],
contentType: ct,
payload: &raw.Frame{msg.Body},
codec: cf,
header: msg.Header,
body: msg.Body,
}
// existing router
r := Router(s.router)
// if the router is present then execute it
if s.opts.Router != nil {
// create a wrapped function
handler := s.opts.Router.ProcessMessage
// execute the wrapper for it
for i := len(s.opts.SubWrappers); i > 0; i-- {
handler = s.opts.SubWrappers[i-1](handler)
}
// set the router
r = rpcRouter{m: handler}
}
return r.ProcessMessage(ctx, rpcMsg)
}
// ServeConn serves a single connection
func (s *rpcServer) ServeConn(sock transport.Socket) {
var wg sync.WaitGroup
@ -97,6 +174,26 @@ func (s *rpcServer) ServeConn(sock transport.Socket) {
return
}
// check the message header for
// Micro-Service is a request
// Micro-Topic is a message
if t := msg.Header["Micro-Topic"]; len(t) > 0 {
// process the event
ev := newEvent(msg)
// TODO: handle the error event
if err := s.HandleEvent(ev); err != nil {
msg.Header["Micro-Error"] = err.Error()
}
// write back some 200
sock.Send(&transport.Message{
Header: msg.Header,
})
// we're done
continue
}
// business as usual
// use Micro-Stream as the stream identifier
// in the event its blank we'll always process
// on the same socket
@ -263,7 +360,7 @@ func (s *rpcServer) ServeConn(sock transport.Socket) {
}
// set the router
r = rpcRouter{handler}
r = rpcRouter{h: handler}
}
// wait for processing to exit
@ -366,6 +463,7 @@ func (s *rpcServer) Init(opts ...Option) error {
r := newRpcRouter()
r.hdlrWrappers = s.opts.HdlrWrappers
r.serviceMap = s.router.serviceMap
r.subWrappers = s.opts.SubWrappers
s.router = r
}
@ -391,29 +489,18 @@ func (s *rpcServer) Handle(h Handler) error {
}
func (s *rpcServer) NewSubscriber(topic string, sb interface{}, opts ...SubscriberOption) Subscriber {
return newSubscriber(topic, sb, opts...)
return s.router.NewSubscriber(topic, sb, opts...)
}
func (s *rpcServer) Subscribe(sb Subscriber) error {
sub, ok := sb.(*subscriber)
if !ok {
return fmt.Errorf("invalid subscriber: expected *subscriber")
}
if len(sub.handlers) == 0 {
return fmt.Errorf("invalid subscriber: no handler functions")
}
s.Lock()
defer s.Unlock()
if err := validateSubscriber(sb); err != nil {
if err := s.router.Subscribe(sb); err != nil {
return err
}
s.Lock()
defer s.Unlock()
_, ok = s.subscribers[sub]
if ok {
return fmt.Errorf("subscriber %v already exists", s)
}
s.subscribers[sub] = nil
s.subscribers[sb] = nil
return nil
}
@ -483,7 +570,7 @@ func (s *rpcServer) Register() error {
}
sort.Strings(handlerList)
var subscriberList []*subscriber
var subscriberList []Subscriber
for e := range s.subscribers {
// Only advertise non internal subscribers
if !e.Options().Internal {
@ -491,7 +578,7 @@ func (s *rpcServer) Register() error {
}
}
sort.Slice(subscriberList, func(i, j int) bool {
return subscriberList[i].topic > subscriberList[j].topic
return subscriberList[i].Topic() > subscriberList[j].Topic()
})
endpoints := make([]*registry.Endpoint, 0, len(handlerList)+len(subscriberList))
@ -535,8 +622,17 @@ func (s *rpcServer) Register() error {
s.registered = true
// subscribe to the topic with own name
sub, err := s.opts.Broker.Subscribe(config.Name, s.HandleEvent)
if err != nil {
return err
}
// save the subscriber
s.subscriber = sub
// subscribe for all of the subscribers
for sb := range s.subscribers {
handler := s.createSubHandler(sb, s.opts)
var opts []broker.SubscribeOption
if queue := sb.Options().Queue; len(queue) > 0 {
opts = append(opts, broker.Queue(queue))
@ -550,10 +646,11 @@ func (s *rpcServer) Register() error {
opts = append(opts, broker.DisableAutoAck())
}
sub, err := config.Broker.Subscribe(sb.Topic(), handler, opts...)
sub, err := config.Broker.Subscribe(sb.Topic(), s.HandleEvent, opts...)
if err != nil {
return err
}
log.Logf("Subscribing %s to topic: %s", node.Id, sub.Topic())
s.subscribers[sb] = []broker.Subscriber{sub}
}
@ -621,6 +718,12 @@ func (s *rpcServer) Deregister() error {
s.registered = false
// close the subscriber
if s.subscriber != nil {
s.subscriber.Unsubscribe()
s.subscriber = nil
}
for sb, subs := range s.subscribers {
for _, sub := range subs {
log.Logf("Unsubscribing %s from topic: %s", node.Id, sub.Topic())