github.com/polarismesh/polaris@v1.17.8/plugin/discoverevent/local/event_local.go (about) 1 /** 2 * Tencent is pleased to support the open source community by making Polaris available. 3 * 4 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. 5 * 6 * Licensed under the BSD 3-Clause License (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * https://opensource.org/licenses/BSD-3-Clause 11 * 12 * Unless required by applicable law or agreed to in writing, software distributed 13 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 14 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 15 * specific language governing permissions and limitations under the License. 16 */ 17 18 package local 19 20 import ( 21 "context" 22 "encoding/json" 23 "fmt" 24 "sync" 25 "time" 26 27 commonlog "github.com/polarismesh/polaris/common/log" 28 "github.com/polarismesh/polaris/common/model" 29 commontime "github.com/polarismesh/polaris/common/time" 30 "github.com/polarismesh/polaris/common/utils" 31 "github.com/polarismesh/polaris/plugin" 32 ) 33 34 const ( 35 PluginName = "discoverEventLocal" 36 defaultBufferSize = 1024 37 ) 38 39 var log = commonlog.RegisterScope(PluginName, "", 0) 40 41 func init() { 42 d := &discoverEventLocal{} 43 plugin.RegisterPlugin(d.Name(), d) 44 } 45 46 type eventBufferHolder struct { 47 writeCursor int 48 readCursor int 49 size int 50 buffer []model.InstanceEvent 51 } 52 53 func newEventBufferHolder(cap int) *eventBufferHolder { 54 return &eventBufferHolder{ 55 writeCursor: 0, 56 readCursor: 0, 57 size: 0, 58 buffer: make([]model.InstanceEvent, cap), 59 } 60 } 61 62 // Reset 重置 eventBufferHolder,使之可以复用 63 func (holder *eventBufferHolder) Reset() { 64 holder.writeCursor = 0 65 holder.readCursor = 0 66 holder.size = 0 67 } 68 69 // Put 放入一个 model.DiscoverEvent 70 func (holder *eventBufferHolder) Put(event model.InstanceEvent) { 71 holder.buffer[holder.writeCursor] = event 72 holder.size++ 73 holder.writeCursor++ 74 } 75 76 // HasNext 判断是否还有下一个元素 77 func (holder *eventBufferHolder) HasNext() bool { 78 return holder.readCursor < holder.size 79 } 80 81 // Next 返回下一个元素 82 // 83 // @return model.DiscoverEvent 元素 84 // @return bool 是否还有下一个元素可以继续读取 85 func (holder *eventBufferHolder) Next() model.InstanceEvent { 86 event := holder.buffer[holder.readCursor] 87 holder.readCursor++ 88 89 return event 90 } 91 92 // Size 当前所存储的有效元素的个数 93 func (holder *eventBufferHolder) Size() int { 94 return holder.size 95 } 96 97 type discoverEventLocal struct { 98 eventCh chan model.InstanceEvent 99 bufferPool sync.Pool 100 curEventBuffer *eventBufferHolder 101 cursor int 102 syncLock sync.Mutex 103 eventHandler func(eventHolder *eventBufferHolder) 104 cancel context.CancelFunc 105 } 106 107 // Name 插件名称 108 // @return string 返回插件名称 109 func (el *discoverEventLocal) Name() string { 110 return PluginName 111 } 112 113 // Initialize 根据配置文件进行初始化插件 discoverEventLocal 114 // @param conf 配置文件内容 115 // @return error 初始化失败,返回 error 信息 116 func (el *discoverEventLocal) Initialize(conf *plugin.ConfigEntry) error { 117 contentBytes, err := json.Marshal(conf.Option) 118 if err != nil { 119 return err 120 } 121 122 config := DefaultDiscoverEventConfig() 123 if err := json.Unmarshal(contentBytes, config); err != nil { 124 return err 125 } 126 if err := config.Validate(); err != nil { 127 return err 128 } 129 130 el.eventCh = make(chan model.InstanceEvent, config.QueueSize) 131 el.eventHandler = el.writeToFile 132 el.bufferPool = sync.Pool{ 133 New: func() interface{} { 134 return newEventBufferHolder(defaultBufferSize) 135 }, 136 } 137 138 el.switchEventBuffer() 139 ctx, cancel := context.WithCancel(context.Background()) 140 go el.Run(ctx) 141 142 el.cancel = cancel 143 return nil 144 } 145 146 // Destroy 执行插件销毁 147 func (el *discoverEventLocal) Destroy() error { 148 if el.cancel != nil { 149 el.cancel() 150 } 151 return nil 152 } 153 154 // PublishEvent 发布一个服务事件 155 func (el *discoverEventLocal) PublishEvent(event model.InstanceEvent) { 156 select { 157 case el.eventCh <- event: 158 return 159 default: 160 // do nothing 161 } 162 } 163 164 var ( 165 subscribeEvents = map[model.InstanceEventType]struct{}{ 166 model.EventInstanceCloseIsolate: {}, 167 model.EventInstanceOpenIsolate: {}, 168 model.EventInstanceOffline: {}, 169 model.EventInstanceOnline: {}, 170 model.EventInstanceTurnHealth: {}, 171 model.EventInstanceTurnUnHealth: {}, 172 } 173 ) 174 175 // Run 执行主逻辑 176 func (el *discoverEventLocal) Run(ctx context.Context) { 177 // 定时刷新事件到日志的定时器 178 syncInterval := time.NewTicker(time.Duration(10) * time.Second) 179 defer syncInterval.Stop() 180 181 for { 182 select { 183 case event := <-el.eventCh: 184 if _, ok := subscribeEvents[event.EType]; !ok { 185 break 186 } 187 188 // 确保事件是顺序的 189 event.CreateTime = time.Now() 190 el.curEventBuffer.Put(event) 191 192 // 触发持久化到 log 阈值 193 if el.curEventBuffer.Size() == defaultBufferSize { 194 go el.eventHandler(el.curEventBuffer) 195 el.switchEventBuffer() 196 } 197 case <-syncInterval.C: 198 go el.eventHandler(el.curEventBuffer) 199 el.switchEventBuffer() 200 case <-ctx.Done(): 201 return 202 } 203 } 204 } 205 206 // switchEventBuffer 换一个新的 buffer 实例继续使用 207 func (el *discoverEventLocal) switchEventBuffer() { 208 el.curEventBuffer = el.bufferPool.Get().(*eventBufferHolder) 209 } 210 211 // writeToFile 事件落盘 212 func (el *discoverEventLocal) writeToFile(eventHolder *eventBufferHolder) { 213 el.syncLock.Lock() 214 defer func() { 215 el.syncLock.Unlock() 216 eventHolder.Reset() 217 el.bufferPool.Put(eventHolder) 218 }() 219 220 for eventHolder.HasNext() { 221 event := eventHolder.Next() 222 log.Info(fmt.Sprintf( 223 "%s|%s|%s|%s|%s|%s|%d|%s|%s", 224 event.Id, 225 event.Namespace, 226 event.Service, 227 event.EType, 228 event.Instance.GetId().GetValue(), 229 event.Instance.GetHost().GetValue(), 230 event.Instance.GetPort().GetValue(), 231 commontime.Time2String(event.CreateTime), 232 utils.LocalHost)) 233 } 234 }