dubbo.apache.org/dubbo-go/v3@v3.1.1/filter/tps/filter.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* 19 Package tps provides a filter for limiting the requests by TPS. 20 21 if you wish to use the TpsLimiter, please add the configuration into your service provider configuration: 22 for example: 23 "UserProvider": 24 registry: "hangzhouzk" 25 protocol : "dubbo" 26 interface : "com.ikurento.user.UserProvider" 27 ... # other configuration 28 tps.limiter: "method-service", # it should be the name of limiter. if the value is 'default', 29 # the MethodServiceTpsLimiter will be used. 30 tps.limit.rejected.handler: "default", # optional, or the name of the implementation 31 if the value of 'tps.limiter' is nil or empty string, the tps filter will do nothing 32 */ 33 package tps 34 35 import ( 36 "context" 37 "sync" 38 ) 39 40 import ( 41 "github.com/dubbogo/gost/log/logger" 42 ) 43 44 import ( 45 "dubbo.apache.org/dubbo-go/v3/common/constant" 46 "dubbo.apache.org/dubbo-go/v3/common/extension" 47 "dubbo.apache.org/dubbo-go/v3/filter" 48 _ "dubbo.apache.org/dubbo-go/v3/filter/handler" 49 _ "dubbo.apache.org/dubbo-go/v3/filter/tps/limiter" 50 "dubbo.apache.org/dubbo-go/v3/protocol" 51 ) 52 53 var ( 54 once sync.Once 55 tpsLimit *tpsLimitFilter 56 ) 57 58 func init() { 59 extension.SetFilter(constant.TpsLimitFilterKey, newTpsLimitFilter) 60 } 61 62 type tpsLimitFilter struct{} 63 64 func newTpsLimitFilter() filter.Filter { 65 if tpsLimit == nil { 66 once.Do(func() { 67 tpsLimit = &tpsLimitFilter{} 68 }) 69 } 70 return tpsLimit 71 } 72 73 // Invoke gets the configured limter to impose TPS limiting 74 func (t *tpsLimitFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { 75 url := invoker.GetURL() 76 tpsLimiter := url.GetParam(constant.TPSLimiterKey, "") 77 rejectedExeHandler := url.GetParam(constant.TPSRejectedExecutionHandlerKey, constant.DefaultKey) 78 if len(tpsLimiter) > 0 { 79 limiter, err := extension.GetTpsLimiter(tpsLimiter) 80 if err != nil { 81 logger.Warn(err) 82 return invoker.Invoke(ctx, invocation) 83 } 84 allow := limiter.IsAllowable(invoker.GetURL(), invocation) 85 if allow { 86 return invoker.Invoke(ctx, invocation) 87 } 88 logger.Errorf("The invocation was rejected due to over the limiter limitation, url: %s ", url.String()) 89 rejectedExecutionHandler, err := extension.GetRejectedExecutionHandler(rejectedExeHandler) 90 if err != nil { 91 logger.Warn(err) 92 } else { 93 return rejectedExecutionHandler.RejectedExecution(url, invocation) 94 } 95 } 96 return invoker.Invoke(ctx, invocation) 97 } 98 99 // OnResponse dummy process, returns the result directly 100 func (t *tpsLimitFilter) OnResponse(_ context.Context, result protocol.Result, _ protocol.Invoker, 101 _ protocol.Invocation) protocol.Result { 102 return result 103 }