gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/registry/memory/memory.go (about) 1 // Package memory provides an in-memory registry 2 package memory 3 4 import ( 5 "context" 6 "sync" 7 "time" 8 9 "github.com/google/uuid" 10 "gitee.com/liuxuezhan/go-micro-v1.18.0/registry" 11 "gitee.com/liuxuezhan/go-micro-v1.18.0/util/log" 12 ) 13 14 var ( 15 sendEventTime = 10 * time.Millisecond 16 ttlPruneTime = time.Second 17 ) 18 19 type node struct { 20 *registry.Node 21 TTL time.Duration 22 LastSeen time.Time 23 } 24 25 type record struct { 26 Name string 27 Version string 28 Metadata map[string]string 29 Nodes map[string]*node 30 Endpoints []*registry.Endpoint 31 } 32 33 type Registry struct { 34 options registry.Options 35 36 sync.RWMutex 37 records map[string]map[string]*record 38 watchers map[string]*Watcher 39 } 40 41 func NewRegistry(opts ...registry.Option) registry.Registry { 42 options := registry.Options{ 43 Context: context.Background(), 44 } 45 46 for _, o := range opts { 47 o(&options) 48 } 49 50 records := getServiceRecords(options.Context) 51 if records == nil { 52 records = make(map[string]map[string]*record) 53 } 54 55 reg := &Registry{ 56 options: options, 57 records: records, 58 watchers: make(map[string]*Watcher), 59 } 60 61 go reg.ttlPrune() 62 63 return reg 64 } 65 66 func (m *Registry) ttlPrune() { 67 prune := time.NewTicker(ttlPruneTime) 68 defer prune.Stop() 69 70 for { 71 select { 72 case <-prune.C: 73 m.Lock() 74 for name, records := range m.records { 75 for version, record := range records { 76 for id, n := range record.Nodes { 77 if n.TTL != 0 && time.Since(n.LastSeen) > n.TTL { 78 log.Debugf("Registry TTL expired for node %s of service %s", n.Id, name) 79 delete(m.records[name][version].Nodes, id) 80 } 81 } 82 } 83 } 84 m.Unlock() 85 } 86 } 87 } 88 89 func (m *Registry) sendEvent(r *registry.Result) { 90 m.RLock() 91 watchers := make([]*Watcher, 0, len(m.watchers)) 92 for _, w := range m.watchers { 93 watchers = append(watchers, w) 94 } 95 m.RUnlock() 96 97 for _, w := range watchers { 98 select { 99 case <-w.exit: 100 m.Lock() 101 delete(m.watchers, w.id) 102 m.Unlock() 103 default: 104 select { 105 case w.res <- r: 106 case <-time.After(sendEventTime): 107 } 108 } 109 } 110 } 111 112 func (m *Registry) Init(opts ...registry.Option) error { 113 for _, o := range opts { 114 o(&m.options) 115 } 116 117 // add services 118 m.Lock() 119 defer m.Unlock() 120 121 records := getServiceRecords(m.options.Context) 122 for name, record := range records { 123 // add a whole new service including all of its versions 124 if _, ok := m.records[name]; !ok { 125 m.records[name] = record 126 continue 127 } 128 // add the versions of the service we dont track yet 129 for version, r := range record { 130 if _, ok := m.records[name][version]; !ok { 131 m.records[name][version] = r 132 continue 133 } 134 } 135 } 136 137 return nil 138 } 139 140 func (m *Registry) Options() registry.Options { 141 return m.options 142 } 143 144 func (m *Registry) Register(s *registry.Service, opts ...registry.RegisterOption) error { 145 m.Lock() 146 defer m.Unlock() 147 148 var options registry.RegisterOptions 149 for _, o := range opts { 150 o(&options) 151 } 152 153 r := serviceToRecord(s, options.TTL) 154 155 if _, ok := m.records[s.Name]; !ok { 156 m.records[s.Name] = make(map[string]*record) 157 } 158 159 if _, ok := m.records[s.Name][s.Version]; !ok { 160 m.records[s.Name][s.Version] = r 161 log.Debugf("Registry added new service: %s, version: %s", s.Name, s.Version) 162 go m.sendEvent(®istry.Result{Action: "update", Service: s}) 163 return nil 164 } 165 166 addedNodes := false 167 for _, n := range s.Nodes { 168 if _, ok := m.records[s.Name][s.Version].Nodes[n.Id]; !ok { 169 addedNodes = true 170 metadata := make(map[string]string) 171 for k, v := range n.Metadata { 172 metadata[k] = v 173 m.records[s.Name][s.Version].Nodes[n.Id] = &node{ 174 Node: ®istry.Node{ 175 Id: n.Id, 176 Address: n.Address, 177 Metadata: metadata, 178 }, 179 TTL: options.TTL, 180 LastSeen: time.Now(), 181 } 182 } 183 } 184 } 185 186 if addedNodes { 187 log.Debugf("Registry added new node to service: %s, version: %s", s.Name, s.Version) 188 go m.sendEvent(®istry.Result{Action: "update", Service: s}) 189 return nil 190 } 191 192 // refresh TTL and timestamp 193 for _, n := range s.Nodes { 194 log.Debugf("Updated registration for service: %s, version: %s", s.Name, s.Version) 195 m.records[s.Name][s.Version].Nodes[n.Id].TTL = options.TTL 196 m.records[s.Name][s.Version].Nodes[n.Id].LastSeen = time.Now() 197 } 198 199 return nil 200 } 201 202 func (m *Registry) Deregister(s *registry.Service) error { 203 m.Lock() 204 defer m.Unlock() 205 206 if _, ok := m.records[s.Name]; ok { 207 if _, ok := m.records[s.Name][s.Version]; ok { 208 for _, n := range s.Nodes { 209 if _, ok := m.records[s.Name][s.Version].Nodes[n.Id]; ok { 210 log.Debugf("Registry removed node from service: %s, version: %s", s.Name, s.Version) 211 delete(m.records[s.Name][s.Version].Nodes, n.Id) 212 } 213 } 214 if len(m.records[s.Name][s.Version].Nodes) == 0 { 215 delete(m.records[s.Name], s.Version) 216 log.Debugf("Registry removed service: %s, version: %s", s.Name, s.Version) 217 } 218 } 219 if len(m.records[s.Name]) == 0 { 220 delete(m.records, s.Name) 221 log.Debugf("Registry removed service: %s", s.Name) 222 } 223 go m.sendEvent(®istry.Result{Action: "delete", Service: s}) 224 } 225 226 return nil 227 } 228 229 func (m *Registry) GetService(name string) ([]*registry.Service, error) { 230 m.RLock() 231 defer m.RUnlock() 232 233 records, ok := m.records[name] 234 if !ok { 235 return nil, registry.ErrNotFound 236 } 237 238 services := make([]*registry.Service, len(m.records[name])) 239 i := 0 240 for _, record := range records { 241 services[i] = recordToService(record) 242 i++ 243 } 244 245 return services, nil 246 } 247 248 func (m *Registry) ListServices() ([]*registry.Service, error) { 249 m.RLock() 250 defer m.RUnlock() 251 252 var services []*registry.Service 253 for _, records := range m.records { 254 for _, record := range records { 255 services = append(services, recordToService(record)) 256 } 257 } 258 259 return services, nil 260 } 261 262 func (m *Registry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) { 263 var wo registry.WatchOptions 264 for _, o := range opts { 265 o(&wo) 266 } 267 268 w := &Watcher{ 269 exit: make(chan bool), 270 res: make(chan *registry.Result), 271 id: uuid.New().String(), 272 wo: wo, 273 } 274 275 m.Lock() 276 m.watchers[w.id] = w 277 m.Unlock() 278 279 return w, nil 280 } 281 282 func (m *Registry) String() string { 283 return "memory" 284 }