github.com/polarismesh/polaris@v1.17.8/common/conn/limit/conn.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 connlimit 19 20 import ( 21 "net" 22 "sync" 23 "time" 24 25 "github.com/polarismesh/polaris/common/log" 26 ) 27 28 // Conn 包装net.Conn 29 // 目的:拦截Close操作,用于listener计数的Release以及activeConns的删除 30 type Conn struct { 31 net.Conn 32 releaseOnce sync.Once 33 closed bool 34 host string 35 address string 36 lastAccess time.Time 37 listener *Listener 38 } 39 40 // Close 包装net.Conn.Close, 用于连接计数 41 func (c *Conn) Close() error { 42 if c.closed { 43 return nil 44 } 45 46 err := c.Conn.Close() 47 c.releaseOnce.Do(func() { 48 // 调用监听的listener,释放计数以及activeConns 49 // 保证只执行一次 50 c.closed = true 51 c.listener.release(c) 52 }) 53 return err 54 } 55 56 // Read 封装net.Conn Read方法,处理readTimeout的场景 57 func (c *Conn) Read(b []byte) (int, error) { 58 if c.listener.readTimeout <= 0 { 59 return c.Conn.Read(b) 60 } 61 62 c.lastAccess = time.Now() 63 if err := c.Conn.SetReadDeadline(time.Now().Add(c.listener.readTimeout)); err != nil { 64 log.Errorf("[connLimit][%s] connection(%s) set read deadline err: %s", 65 c.listener.protocol, c.address, err.Error()) 66 } 67 n, err := c.Conn.Read(b) 68 if err == nil { 69 return n, nil 70 } 71 72 if e, ok := err.(net.Error); ok && e.Timeout() { 73 if time.Since(c.lastAccess) >= c.listener.readTimeout { 74 log.Errorf("[connLimit][%s] read timeout(%v): %s, connection(%s) will be closed by server", 75 c.listener.protocol, c.listener.readTimeout, err.Error(), c.address) 76 } 77 } 78 return n, err 79 } 80 81 // 判断conn是否还有效 82 func (c *Conn) isValid() bool { 83 return !c.closed 84 }