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  }