问题描述
我正在构建一个面向性能的 REST-API。 骨架是用go-swagger建造的。
API 有 3 毫秒的响应时间,并且在单次使用方面取得了成功,而响应时间仅在 0.5 毫秒 - 0.8 毫秒之间。对 redis 进行了两次调用。
池是这样启动的:
func createPool(server string) *redis.Pool {
return &redis.Pool{
MaxIdle: 500,MaxActive: 10000,IdleTimeout: 5 * time.Second,//MaxConnLifetime: 1800 * time.Microsecond,Dial: func() (redis.Conn,error) {
c,err := redis.Dial("tcp",server)
if err != nil {
return nil,err
}
return c,err
},TestOnBorrow: func(c redis.Conn,t time.Time) error {
if time.Since(t) < (3 * time.Second) {
return nil
}
_,err := c.Do("PING")
if err != nil {
}
return err
},}
这是唯一使用游泳池的地方:
func GetValue(params Params) []int64 {
timeNow := time.Now()
conn := data.Pool.Get()
value1 := Foo(conn)
value2 := Bar(value1,conn)
conn.Close()
defer Log(value1,value2)
return value2}
所以基本上一开始我从池中获得一个连接,用于两个 redis 请求,然后关闭它。我以前使用过 defer conn.Close()
,因为它在文档中有所说明,但它也不起作用。 vm.overcommit_memory=1
和 net.core.somaxconn=512
已在服务器上设置。
单独使用API没有问题。 当处于压力下时,例如每秒 4000 个请求,它会在前 10 秒内工作,然后变得非常缓慢并且无法及时响应(开始时声明的 3 毫秒)。
当我检查 ActiveCount 和 IdleCount 时,值在 2 到 5 之间并且始终相同。 MaxActive 值为 10.000 时,是否应该有更多的连接可能?还是我遗漏了一些关键设置?
解决方法
整个问题不依赖于 redis。端口侦听的套接字被淹没,因为在压力测试时 TCP 连接没有正确关闭。
这导致在 time_wait-state 中有大约 60k 个连接。使用 live-traffic 代替 jMeter 进行压力测试时,问题得到解决。