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 }