http server supports subscriber

This commit is contained in:
武新飞
2018-12-19 15:33:23 +08:00
committed by Vasiliy Tolstov
parent 24f8e6b137
commit 3c3b81d9cd
5 changed files with 499 additions and 27 deletions

94
http.go
View File

@@ -3,28 +3,54 @@ package http
import (
"errors"
"fmt"
"net"
"net/http"
"sort"
"sync"
"github.com/micro/go-log"
"github.com/micro/go-micro/cmd"
"github.com/micro/go-micro/registry"
"github.com/micro/go-micro/broker"
"github.com/micro/go-micro/server"
"github.com/micro/go-micro/cmd"
"github.com/micro/go-micro/codec"
"github.com/micro/go-micro/registry"
"github.com/micro/go-plugins/codec/jsonrpc"
"github.com/micro/go-plugins/codec/protorpc"
)
var (
defaultCodecs = map[string]codec.NewCodec{
"application/json": jsonrpc.NewCodec,
"application/json-rpc": jsonrpc.NewCodec,
"application/protobuf": protorpc.NewCodec,
"application/proto-rpc": protorpc.NewCodec,
"application/octet-stream": protorpc.NewCodec,
}
)
type httpServer struct {
sync.Mutex
opts server.Options
hd server.Handler
exit chan chan error
registerOnce sync.Once
subscribers map[*subscriber][]broker.Subscriber
}
func init() {
cmd.DefaultServers["http"] = NewServer
}
func (h *httpServer) newCodec(contentType string) (codec.NewCodec, error) {
if cf, ok := h.opts.Codecs[contentType]; ok {
return cf, nil
}
if cf, ok := defaultCodecs[contentType]; ok {
return cf, nil
}
return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType)
}
func (h *httpServer) Options() server.Options {
h.Lock()
opts := h.opts
@@ -79,20 +105,30 @@ func (h *httpServer) NewHandler(handler interface{}, opts ...server.HandlerOptio
}
func (h *httpServer) NewSubscriber(topic string, handler interface{}, opts ...server.SubscriberOption) server.Subscriber {
var options server.SubscriberOptions
for _, o := range opts {
o(&options)
}
return &httpSubscriber{
opts: options,
topic: topic,
hd: handler,
}
return newSubscriber(topic, handler, opts...)
}
func (h *httpServer) Subscribe(s server.Subscriber) error {
return errors.New("subscribe is not supported")
func (h *httpServer) Subscribe(sb server.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")
}
if err := validateSubscriber(sb); err != nil {
return err
}
h.Lock()
defer h.Unlock()
_, ok = h.subscribers[sub]
if ok {
return fmt.Errorf("subscriber %v already exists", h)
}
h.subscribers[sub] = nil
return nil
}
func (h *httpServer) Register() error {
@@ -104,12 +140,42 @@ func (h *httpServer) Register() error {
service := serviceDef(opts)
service.Endpoints = eps
h.Lock()
var subscriberList []*subscriber
for e := range h.subscribers {
// Only advertise non internal subscribers
if !e.Options().Internal {
subscriberList = append(subscriberList, e)
}
}
sort.Slice(subscriberList, func(i, j int) bool {
return subscriberList[i].topic > subscriberList[j].topic
})
for _, e := range subscriberList {
service.Endpoints = append(service.Endpoints, e.Endpoints()...)
}
h.Unlock()
rOpts := []registry.RegisterOption{
registry.RegisterTTL(opts.RegisterTTL),
}
h.registerOnce.Do(func() {
log.Logf("Registering node: %s", opts.Name+"-"+opts.Id)
for sb, _ := range h.subscribers {
handler := h.createSubHandler(sb, opts)
var subOpts []broker.SubscribeOption
if queue := sb.Options().Queue; len(queue) > 0 {
subOpts = append(subOpts, broker.Queue(queue))
}
sub, err := opts.Broker.Subscribe(sb.Topic(), handler, subOpts...)
if err != nil {
log.Logf("Registering subscriber: %s, err: %s", sb.Topic, err)
return
}
h.subscribers[sb] = []broker.Subscriber{sub}
}
})
return opts.Registry.Register(service, rOpts...)