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 }