github.com/godevsig/adaptiveservice@v0.9.23/adaptiveservice.go (about)

     1  // Package adaptiveservice is a message oriented micro service framework.
     2  //
     3  // Servers define micro services identified as name of "publisher_service" and
     4  // publish them to all available scopes:
     5  // in same process, and further in same OS, and then further in same local
     6  // network, and then public network where a public root registry address needs
     7  // to be configured.
     8  // In process and OS scope, one service name can only be announced once,
     9  // duplicated service name is treated as error.
    10  // In network scope, there can be multiple services with the same name,
    11  // in this case, each service provider publishes the service "publisher_service"
    12  // along with an unique provider ID.
    13  //
    14  // Clients then discover wanted micro services in a way that shortest scope comes
    15  // first. The discover() API returns a connection channel, reading the channel the
    16  // client will get one or more connections, with each represents a connection
    17  // to one of the service providers providing the wanted micro service.
    18  // The connection then can be used to send/receive messages to/from the service provider.
    19  //
    20  // Connections can be multiplexed on client side: NewStream() API creates a new
    21  // context in which the messages are transferred independently from other contexts
    22  // over the same underlying connection. The intention of the multiplexer is to have
    23  // scalability on client side: users use this mechanism to send parallel request
    24  // messages towards the same service provider to increase execution concurrency.
    25  //
    26  // For server side, the incoming messages are handled in auto-scaled worker pool,
    27  // so the multiplexer used on client side is not needed on server side.
    28  // Servers listen to different transports for all available scopes:
    29  //  process scope, go channels are used
    30  //  OS scope, unix domain socket is used
    31  //  network scope, tcp socket is used
    32  //
    33  // Messages that satisfy Handle() interface are known messages. Typically
    34  // server defines Handle() method for every message type it can handle,
    35  // then when the known message arrived on one of the transports it is
    36  // listening, the message is delivered to one of the workers in which
    37  // the message's Handle() is called.
    38  // Clients do not define Handle() method, they just send and receive message
    39  // in a natural synchronized fashion.
    40  //
    41  // Services that are behind NAT can be auto proxied by the builtin reverseProxy
    42  // service provided by the daemon server in the local network or by the root
    43  // registry.
    44  package adaptiveservice
    45  
    46  import (
    47  	"errors"
    48  	"fmt"
    49  	"io"
    50  	"math/rand"
    51  	"os"
    52  	"os/signal"
    53  	"reflect"
    54  	"strings"
    55  	"sync"
    56  	"syscall"
    57  	"time"
    58  
    59  	"github.com/niubaoshu/gotiny"
    60  )
    61  
    62  // Scope is publishing and discovering scope
    63  type Scope uint16
    64  
    65  const (
    66  	// ScopeProcess is a scope where publishing and discovering services
    67  	// only happen in same process.
    68  	ScopeProcess Scope = 1 << iota
    69  	// ScopeOS is a scope where publishing and discovering services
    70  	// only happen in same OS.
    71  	ScopeOS
    72  	// ScopeLAN is a scope where publishing and discovering services
    73  	// only happen in same local network.
    74  	ScopeLAN
    75  	// ScopeWAN is a scope where publishing and discovering services
    76  	// only happen in same reachable public network.
    77  	ScopeWAN
    78  	// ScopeNetwork is a shortcut for ScopeLAN and ScopeWAN
    79  	ScopeNetwork = ScopeLAN | ScopeWAN
    80  	// ScopeAll includes all scopes.
    81  	ScopeAll = ScopeProcess | ScopeOS | ScopeLAN | ScopeWAN
    82  
    83  	// OK can be returned by known messages as reply to indicate
    84  	// everything is OK. Client should use type int to receive it.
    85  	OK = 0
    86  )
    87  
    88  var (
    89  	// ErrServiceNotReachable is an error where the service exists
    90  	// but somehow can not be reached, e.g. the service is behind NAT.
    91  	ErrServiceNotReachable = errors.New("service not reachable")
    92  	// ErrConnReset is an error where the connection was forced closed
    93  	// by peer.
    94  	ErrConnReset = errors.New("connection reset by peer")
    95  	// ErrServerClosed is an error where the server was closed by signal.
    96  	ErrServerClosed = errors.New("server closed by signal")
    97  	// ErrRecvTimeout is an error where no data was received within
    98  	// specified duration.
    99  	ErrRecvTimeout = errors.New("receive timeout")
   100  )
   101  
   102  type errServiceNotFound struct {
   103  	publisher string
   104  	service   string
   105  }
   106  
   107  func (e errServiceNotFound) Error() string {
   108  	return "service not found: " + e.publisher + "_" + e.service
   109  }
   110  
   111  // ErrServiceNotFound returns an error that no wanted service was found
   112  func ErrServiceNotFound(publisher, service string) error {
   113  	return errServiceNotFound{publisher, service}
   114  }
   115  
   116  type streamIO struct {
   117  	stream Stream
   118  	rbuff  []byte
   119  }
   120  
   121  func (sio *streamIO) Read(p []byte) (n int, err error) {
   122  	if len(sio.rbuff) == 0 {
   123  		if err := sio.stream.Recv(&sio.rbuff); err != nil {
   124  			return 0, err
   125  		}
   126  	}
   127  	n = copy(p, sio.rbuff)
   128  	sio.rbuff = sio.rbuff[n:]
   129  	return
   130  }
   131  
   132  func (sio *streamIO) Write(p []byte) (n int, err error) {
   133  	if err := sio.stream.Send(p); err != nil {
   134  		return 0, err
   135  	}
   136  	return len(p), nil
   137  }
   138  
   139  func (sio *streamIO) Close() error {
   140  	return sio.stream.Send(io.EOF)
   141  }
   142  
   143  // NewStreamIO wraps the stream to be an io.ReadWriteCloser in which
   144  // Read() is a Stream.Recv() that only receives []byte,
   145  // Write is a Stream.Send() that only sends []byte.
   146  // Use Read() Write() in pair on the client/server peer, don't mix use
   147  // them with Send() or Recv().
   148  func NewStreamIO(stream Stream) io.ReadWriteCloser {
   149  	return &streamIO{stream: stream}
   150  }
   151  
   152  // Logger is the logger interface.
   153  type Logger interface {
   154  	Debugf(format string, args ...interface{})
   155  	Infof(format string, args ...interface{})
   156  	Warnf(format string, args ...interface{})
   157  	Errorf(format string, args ...interface{})
   158  }
   159  
   160  // LoggerNull prints no log
   161  type LoggerNull struct{}
   162  
   163  // Debugf is Debugf
   164  func (LoggerNull) Debugf(format string, args ...interface{}) {}
   165  
   166  // Infof is Infof
   167  func (LoggerNull) Infof(format string, args ...interface{}) {}
   168  
   169  // Warnf is Warnf
   170  func (LoggerNull) Warnf(format string, args ...interface{}) {}
   171  
   172  // Errorf is Errorf
   173  func (LoggerNull) Errorf(format string, args ...interface{}) {}
   174  
   175  // LoggerAll prints all regardless of loglevel
   176  type LoggerAll struct{}
   177  
   178  // Debugf is Debugf
   179  func (LoggerAll) Debugf(format string, args ...interface{}) {
   180  	fmt.Printf("[AS DEBUG] "+format+"\n", args...)
   181  }
   182  
   183  // Infof is Infof
   184  func (LoggerAll) Infof(format string, args ...interface{}) {
   185  	fmt.Printf("[AS INFO] "+format+"\n", args...)
   186  }
   187  
   188  // Warnf is Warnf
   189  func (LoggerAll) Warnf(format string, args ...interface{}) {
   190  	fmt.Printf("[AS WARN] "+format+"\n", args...)
   191  }
   192  
   193  // Errorf is Errorf
   194  func (LoggerAll) Errorf(format string, args ...interface{}) {
   195  	fmt.Printf("[AS ERROR] "+format+"\n", args...)
   196  }
   197  
   198  type errorRecover interface {
   199  	Error() error
   200  	String() string
   201  	Recover() (recovered bool) // return true if the error has been recovered.
   202  }
   203  
   204  type noError struct{}
   205  
   206  func (e noError) Error() error {
   207  	return nil
   208  }
   209  
   210  func (e noError) String() string {
   211  	return "no error"
   212  }
   213  
   214  func (e noError) Recover() bool {
   215  	return false
   216  }
   217  
   218  type unrecoverableError struct {
   219  	err error
   220  }
   221  
   222  func (e unrecoverableError) Error() error {
   223  	return e.err
   224  }
   225  
   226  func (e unrecoverableError) String() string {
   227  	return "unrecoverable error"
   228  }
   229  
   230  func (e unrecoverableError) Recover() bool {
   231  	return false
   232  }
   233  
   234  type customErrorRecover struct {
   235  	err         error
   236  	str         string
   237  	recoverFunc func() bool
   238  }
   239  
   240  func (e customErrorRecover) Error() error {
   241  	return e.err
   242  }
   243  
   244  func (e customErrorRecover) String() string {
   245  	return e.str
   246  }
   247  
   248  func (e customErrorRecover) Recover() bool {
   249  	return e.recoverFunc()
   250  }
   251  
   252  var (
   253  	sigCleaner struct {
   254  		sync.Mutex
   255  		closers []closer
   256  	}
   257  
   258  	sigOnce sync.Once
   259  )
   260  
   261  type closer interface {
   262  	close()
   263  }
   264  
   265  // allows io.Closer to be closer
   266  type ioCloser func() error
   267  
   268  func (c ioCloser) close() {
   269  	c()
   270  }
   271  
   272  func addSigCloser(c closer) {
   273  	sigCleaner.Lock()
   274  	sigCleaner.closers = append(sigCleaner.closers, c)
   275  	sigCleaner.Unlock()
   276  }
   277  
   278  func initSigCleaner(lg Logger) {
   279  	sigOnce.Do(func() {
   280  		// handle signal
   281  		signal.Ignore(syscall.SIGHUP)
   282  		sigChan := make(chan os.Signal, 1)
   283  		signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
   284  		go func() {
   285  			sig := <-sigChan
   286  			lg.Warnf("signal: %s", sig.String())
   287  			sigCleaner.Lock()
   288  			for _, c := range sigCleaner.closers {
   289  				c.close()
   290  			}
   291  			sigCleaner.Unlock()
   292  		}()
   293  	})
   294  }
   295  
   296  // RegisterType registers the type infomation to encoding sub system.
   297  func RegisterType(i interface{}) {
   298  	//gotiny.Register(i)
   299  	rt := reflect.TypeOf(i)
   300  	gotiny.RegisterName(rt.String(), rt)
   301  }
   302  
   303  // test if pattern matches str
   304  //   "*" matches all
   305  //  "*bar*" matches bar, foobar, or foobarabc
   306  //  "foo*abc*" matches foobarabc, foobarabc123, or fooabc
   307  func wildcardMatch(pattern, str string) bool {
   308  	if len(pattern) == 0 {
   309  		return false
   310  	}
   311  	strs := strings.Split(pattern, "*")
   312  	var pos, index int
   313  	if index = strings.Index(str, strs[0]); index != 0 {
   314  		return false
   315  	}
   316  	end := strs[len(strs)-1]
   317  	if index = strings.LastIndex(str, end); index+len(end) != len(str) {
   318  		return false
   319  	}
   320  	for i, substr := range strs {
   321  		if i == 0 || i == len(strs)-1 || len(substr) == 0 {
   322  			continue
   323  		}
   324  		index = strings.Index(str[pos:], substr)
   325  		if index == -1 {
   326  			return false
   327  		}
   328  		pos += index + len(substr)
   329  	}
   330  	return true
   331  }
   332  
   333  func init() {
   334  	rand.Seed(time.Now().UnixNano())
   335  	// basic types
   336  	RegisterType(int(0))
   337  	RegisterType(int8(0))
   338  	RegisterType(int16(0))
   339  	RegisterType(int32(0))
   340  	RegisterType(int64(0))
   341  	RegisterType(uint(0))
   342  	RegisterType(uint8(0))
   343  	RegisterType(uint16(0))
   344  	RegisterType(uint32(0))
   345  	RegisterType(uint64(0))
   346  	RegisterType(float32(0))
   347  	RegisterType(float64(0))
   348  	RegisterType(complex64(0i))
   349  	RegisterType(complex128(0i))
   350  	RegisterType(uintptr(0))
   351  	RegisterType(false)
   352  	RegisterType("")
   353  	//RegisterType([]byte(nil))
   354  	RegisterType([]int(nil))
   355  	RegisterType([]int8(nil))
   356  	RegisterType([]int16(nil))
   357  	RegisterType([]int32(nil))
   358  	RegisterType([]int64(nil))
   359  	RegisterType([]uint(nil))
   360  	RegisterType([]uint8(nil))
   361  	RegisterType([]uint16(nil))
   362  	RegisterType([]uint32(nil))
   363  	RegisterType([]uint64(nil))
   364  	RegisterType([]float32(nil))
   365  	RegisterType([]float64(nil))
   366  	RegisterType([]complex64(nil))
   367  	RegisterType([]complex128(nil))
   368  	RegisterType([]uintptr(nil))
   369  	RegisterType([]bool(nil))
   370  	RegisterType([]string(nil))
   371  	// error types
   372  	RegisterType(errors.New(""))
   373  	RegisterType(fmt.Errorf("%w", io.EOF))
   374  }
   375  
   376  // Dummy annotation marking that the value x escapes,
   377  // for use in cases where the reflect code is so clever that
   378  // the compiler cannot follow.
   379  func escapes(x interface{}) {
   380  	if dummy.b {
   381  		dummy.x = x
   382  	}
   383  }
   384  
   385  var dummy struct {
   386  	b bool
   387  	x interface{}
   388  }