github.com/polarismesh/polaris@v1.17.8/apiserver/grpcserver/cache.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 grpcserver
    19  
    20  import (
    21  	"fmt"
    22  
    23  	"github.com/gogo/protobuf/proto"
    24  	lru "github.com/hashicorp/golang-lru"
    25  	"google.golang.org/grpc"
    26  
    27  	"github.com/polarismesh/polaris/common/metrics"
    28  	"github.com/polarismesh/polaris/plugin"
    29  )
    30  
    31  const (
    32  	enableProtobufCacheKey = "enableCacheProto"
    33  	sizeProtobufCacheKey   = "sizeCacheProto"
    34  )
    35  
    36  // MessageToCache
    37  type MessageToCache func(m interface{}) *CacheObject
    38  
    39  // Cache
    40  type Cache interface {
    41  	// Get
    42  	Get(cacheType string, key string) *CacheObject
    43  	// Put
    44  	Put(v *CacheObject) (*CacheObject, bool)
    45  }
    46  
    47  // CacheObject
    48  type CacheObject struct {
    49  	// OriginVal
    50  	OriginVal proto.Message
    51  	// preparedVal
    52  	preparedVal *grpc.PreparedMsg
    53  	// CacheType
    54  	CacheType string
    55  	// Key
    56  	Key string
    57  }
    58  
    59  func (c *CacheObject) GetPreparedMessage() *grpc.PreparedMsg {
    60  	return c.preparedVal
    61  }
    62  
    63  func (c *CacheObject) PrepareMessage(stream grpc.ServerStream) error {
    64  	pmsg := &grpc.PreparedMsg{}
    65  	if err := pmsg.Encode(stream, c.OriginVal); err != nil {
    66  		return err
    67  	}
    68  	c.preparedVal = pmsg
    69  	return nil
    70  }
    71  
    72  // protobufCache PB object cache, reduce the overhead caused by the serialization of the PB repeated object
    73  type protobufCache struct {
    74  	enabled       bool
    75  	cahceRegistry map[string]*lru.ARCCache
    76  }
    77  
    78  // NewCache Component a PB cache pool
    79  func NewCache(options map[string]interface{}, cacheType []string) (Cache, error) {
    80  	enabled, _ := options[enableProtobufCacheKey].(bool)
    81  
    82  	if !enabled {
    83  		return nil, nil
    84  	}
    85  
    86  	size, _ := options[sizeProtobufCacheKey].(int)
    87  	if size == 0 {
    88  		size = 128
    89  	}
    90  
    91  	cahceRegistry := make(map[string]*lru.ARCCache)
    92  
    93  	for i := range cacheType {
    94  		cache, err := lru.NewARC(size)
    95  		if err != nil {
    96  			return nil, fmt.Errorf("init protobuf=[%s] cache fail : %+v", cacheType[i], err)
    97  		}
    98  		cahceRegistry[cacheType[i]] = cache
    99  	}
   100  
   101  	return &protobufCache{
   102  		enabled:       enabled,
   103  		cahceRegistry: cahceRegistry,
   104  	}, nil
   105  }
   106  
   107  // Get value by cacheType and key
   108  func (pc *protobufCache) Get(cacheType string, key string) *CacheObject {
   109  	c, ok := pc.cahceRegistry[cacheType]
   110  	if !ok {
   111  		return nil
   112  	}
   113  
   114  	val, exist := c.Get(key)
   115  	plugin.GetStatis().ReportCallMetrics(metrics.CallMetric{
   116  		Type:     metrics.ProtobufCacheCallMetric,
   117  		Protocol: cacheType,
   118  		Success:  exist,
   119  		Times:    1,
   120  	})
   121  
   122  	if val == nil {
   123  		return nil
   124  	}
   125  
   126  	return val.(*CacheObject)
   127  }
   128  
   129  // Put save cache value
   130  func (pc *protobufCache) Put(v *CacheObject) (*CacheObject, bool) {
   131  	if v == nil {
   132  		return nil, false
   133  	}
   134  
   135  	cacheType := v.CacheType
   136  	key := v.Key
   137  
   138  	c, ok := pc.cahceRegistry[cacheType]
   139  	if !ok {
   140  		return nil, false
   141  	}
   142  
   143  	c.Add(key, v)
   144  	return v, true
   145  }