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.
lal/util/connstat.go

83 lines
2.0 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package util
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
}