github.com/cloudwego/kitex@v0.9.0/pkg/remote/bound/limiter_inbound.go (about) 1 /* 2 * Copyright 2021 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package bound 18 19 import ( 20 "context" 21 "fmt" 22 "net" 23 "reflect" 24 25 "github.com/cloudwego/kitex/pkg/kerrors" 26 "github.com/cloudwego/kitex/pkg/limiter" 27 "github.com/cloudwego/kitex/pkg/remote" 28 ) 29 30 // NewServerLimiterHandler creates a new server limiter handler. 31 func NewServerLimiterHandler(conLimit limiter.ConcurrencyLimiter, qpsLimit limiter.RateLimiter, reporter limiter.LimitReporter, qpsLimitPostDecode bool) remote.InboundHandler { 32 return &serverLimiterHandler{conLimit, qpsLimit, reporter, qpsLimitPostDecode} 33 } 34 35 type serverLimiterHandler struct { 36 connLimit limiter.ConcurrencyLimiter 37 qpsLimit limiter.RateLimiter 38 reporter limiter.LimitReporter 39 qpsLimitPostDecode bool 40 } 41 42 // OnActive implements the remote.InboundHandler interface. 43 func (l *serverLimiterHandler) OnActive(ctx context.Context, conn net.Conn) (context.Context, error) { 44 if l.connLimit.Acquire(ctx) { 45 return ctx, nil 46 } 47 if l.reporter != nil { 48 l.reporter.ConnOverloadReport() 49 } 50 return ctx, kerrors.ErrConnOverLimit 51 } 52 53 // OnRead implements the remote.InboundHandler interface. 54 func (l *serverLimiterHandler) OnRead(ctx context.Context, conn net.Conn) (context.Context, error) { 55 if !l.qpsLimitPostDecode { 56 if l.qpsLimit.Acquire(ctx) { 57 return ctx, nil 58 } 59 if l.reporter != nil { 60 l.reporter.QPSOverloadReport() 61 } 62 return ctx, kerrors.ErrQPSOverLimit 63 } 64 return ctx, nil 65 } 66 67 // OnInactive implements the remote.InboundHandler interface. 68 func (l *serverLimiterHandler) OnInactive(ctx context.Context, conn net.Conn) context.Context { 69 l.connLimit.Release(ctx) 70 return ctx 71 } 72 73 // OnMessage implements the remote.InboundHandler interface. 74 func (l *serverLimiterHandler) OnMessage(ctx context.Context, args, result remote.Message) (context.Context, error) { 75 if l.qpsLimitPostDecode { 76 if l.qpsLimit.Acquire(ctx) { 77 return ctx, nil 78 } 79 if l.reporter != nil { 80 l.reporter.QPSOverloadReport() 81 } 82 return ctx, kerrors.ErrQPSOverLimit 83 } 84 return ctx, nil 85 } 86 87 func DeepEqual(bound1, bound2 remote.InboundHandler) bool { 88 switch b1 := bound1.(type) { 89 case *serverLimiterHandler: 90 b2, ok := bound2.(*serverLimiterHandler) 91 if !ok { 92 return false 93 } 94 return reflect.DeepEqual(b1.connLimit, b2.connLimit) && reflect.DeepEqual(b1.reporter, b2.reporter) && 95 fmt.Sprintf("%T", b1.qpsLimit) == fmt.Sprintf("%T", b2.qpsLimit) && 96 b1.qpsLimitPostDecode == b2.qpsLimitPostDecode 97 default: 98 return reflect.DeepEqual(bound1, bound2) 99 } 100 }