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  }