1、Go 连接redis的方法:
package que
import (
"fmt"
"time"
"github.com/gomodule/redigo/redis"
)
var (
pool *redis.Pool
localhost = "" // 127.0.0.1
port = "6379"
addr = localhost + ":" + port
Password = ""
)
func init() {
initRides()
// InitReceiver()
}
func initRides() {
pool = &redis.Pool{
IdleTimeout: 180 * time.Second,
Dial: func() (redis.Conn, error) {
conn, err := redis.Dial("tcp", addr, redis.DialPassword(Password))
if err != nil {
return nil, err
}
return conn, nil
},
}
}
其中如果没有 redis.DialPassword(Password),则连接redis时可能会报错:NOAUTH Authentication required.
或者可以使用下面这种设置方式解决认证问题:
func initRides() {
pool = &redis.Pool{
IdleTimeout: 180 * time.Second,
Dial: func() (redis.Conn, error) {
conn, err := redis.Dial("tcp", addr)
if err != nil {
return nil, err
}
if _, err := conn.Do("AUTH", Password); err != nil {
conn.Close()
return nil, err
}
return conn, nil
},
}
}
2、根据业务需求,在main的init里面调用InitReceiver方法,当需要处理大量数据的时候,接口不能做出及时反馈,这时就需要类似的模型来解决该问题了:
func init() {
initRides()
InitReceiver()
}
func InitReceiver() {
go func() {
for {
var conn = pool.Get()
defer conn.Close()
// Do some thing
conn.Do("set", "test", "test1111")
line, _ := redis.String(conn.Do("get", "test"))
fmt.Println(line)
}
}()
}
3、代码跑起来之后,使用命令:
netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
查看TCP的状态信息,其中ESTABLISHED状态的存在1万多个:
CLOSE_WAIT 1
ESTABLISHED 10015
SYN_SENT 1
TIME_WAIT 15
下面是 TCP正常连接建立和终止所对应的状态图:
相关TCP状态解释:
LISTEN: 侦听来自远方的TCP端口的连接请求;
SYN_SENT: 在发送连接请求后等待匹配的连接请求;
SYN_RECV: 在收到和发送一个连接请求后等待对方对连接请求的确认;
ESTABLISHED: 代表一个打开的连接;
FIN_WAIT1: 等待远程TCP连接中断请求, 或先前的连接中断请求的确认;
FIN_WAIT2: 从远程TCP等待连接中断请求;
CLOSE_WAIT: 等待从本地用户发来的连接中断请求;
CLOSING: 等待远程TCP对连接中断的确认;
LAST_ACK: 等待原来的发向远程TCP的连接中断请求的确认;
TIME_WAIT: 等待足够的时间以确保远程TCP接收到连接中断请求的确认;
CLOSE: 没有任何连接状态;
注(参考出处:)
4、当我们推出程序之后:
[root ~]# netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
CLOSE_WAIT 1
ESTABLISHED 15
SYN_SENT 1
TIME_WAIT 10013
ESTABLISHED状态的连接被中断了,会通过TIME_WAIT的状态保留一段时间,这段时间过了才会释放这个端口,但是如果再这段时间内还有大量的请求的时候,就会产生大量的TIME_WAIT状态的连接,这些连接占着端口,也会占用大量的资源。
5、解决方法,增加 MaxIdle 和 MaxActive :
func initRides() {
pool = &redis.Pool{
MaxIdle: 30,
MaxActive: 30,
IdleTimeout: 180 * time.Second,
Dial: func() (redis.Conn, error) {
conn, err := redis.Dial("tcp", addr, redis.DialPassword(Password))
if err != nil {
return nil, err
}
return conn, nil
},
}
}
maxIdle,最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连
接将被标记为不可用,然后被释放。设为0表示无限制。
MaxActive,连接池的最大数据库连接数。设为0表示无限制。
maxActive是最大激活连接数,这里取值为30,表示同时最多有30个数据库连接。
maxIdle是最大的空闲连接数,这里取值为30,表示即使没有数据库连接时依然可以保持30空闲的
连接,而不被清除,随时处于待命状态。
设置了之后效果显著:
[root ~]# netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
CLOSE_WAIT 2
ESTABLISHED 25
TIME_WAIT 67