You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
naza/pkg/connstat/connstat.go

84 lines
2.1 KiB
Go

// package connstat 待整理,未正式使用
package connstat
import (
"sync/atomic"
"time"
)
// 高性能场景下实现长连接流数据读写超时功能
// 不使用Go的库函数SetDeadline
// 也不在每次读写数据时使用time now获取读写时间
// 允许出现两秒左右的误差
type ConnStat struct {
readTimeout int64
writeTimeout int64
totalReadByte uint64
totalWriteByte uint64
prevTotalReadByte uint64
prevTotalWriteByte uint64
lastReadActiveTick int64
lastWriteActiveTick int64
}
// 单位秒设置为0则用于不超时
func (cs *ConnStat) Start(readTimeout int64, writeTimeout int64) {
cs.readTimeout = readTimeout
cs.writeTimeout = writeTimeout
now := time.Now().Unix()
cs.lastReadActiveTick = now
cs.lastWriteActiveTick = now
}
func (cs *ConnStat) Read(n int) {
atomic.AddUint64(&cs.totalReadByte, uint64(n))
}
func (cs *ConnStat) Write(n int) {
atomic.AddUint64(&cs.totalWriteByte, uint64(n))
}
// 检查时传入当前时间戳。检查频率应该小于超时阈值。频率越低,则越精确
func (cs *ConnStat) Check(now int64) (isReadTimeout bool, isWriteTimeout bool) {
if cs.readTimeout == 0 { // 没有设置,则不用检查
isReadTimeout = false
} else {
trb := atomic.LoadUint64(&cs.totalReadByte)
if trb == 0 { // 历史从来没有收到过数据
isReadTimeout = (now - cs.lastReadActiveTick) > cs.readTimeout
} else {
if trb-cs.prevTotalReadByte > 0 { // 距离上次检查有收到过数据
isReadTimeout = false
cs.lastReadActiveTick = now
} else {
isReadTimeout = (now - cs.lastReadActiveTick) > cs.readTimeout
}
}
cs.prevTotalReadByte = trb
}
if cs.writeTimeout == 0 {
isWriteTimeout = false
} else {
twb := atomic.LoadUint64(&cs.totalWriteByte)
if twb == 0 {
isWriteTimeout = (now - cs.lastWriteActiveTick) > cs.writeTimeout
} else {
if twb-cs.prevTotalWriteByte > 0 {
isWriteTimeout = false
cs.lastWriteActiveTick = now
} else {
isWriteTimeout = (now - cs.lastWriteActiveTick) > cs.writeTimeout
}
}
cs.prevTotalWriteByte = twb
}
return
}