首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >redigo:获取拨号tcp: connect:无法分配请求的地址

redigo:获取拨号tcp: connect:无法分配请求的地址
EN

Stack Overflow用户
提问于 2016-06-15 07:04:32
回答 1查看 14K关注 0票数 7

我有一个应用程序,大约每秒读取400次,每秒100次写入redis (驻留在redislabs上)。应用程序使用github.com/garyburd/redigo包作为redis代理。

我有两个函数,它们是唯一用来读写的:

代码语言:javascript
复制
func getCachedVPAIDConfig(key string) chan *cachedVPAIDConfig {
    c := make(chan *cachedVPAIDConfig)
    go func() {
        p := pool.Get()
        defer p.Close()

        switch p.Err() {
        case nil:
            item, err := redis.Bytes(p.Do("GET", key))
            if err != nil {
                c <- &cachedVPAIDConfig{nil, err}
                return
            }

            c <- &cachedVPAIDConfig{item, nil}
        default:
            c <- &cachedVPAIDConfig{nil, p.Err()}
            return
        }
    }()
    return c
}



func setCachedVPAIDConfig(key string, j []byte) chan error {
    c := make(chan error)
    go func() {
        p := pool.Get()
        defer p.Close()

        switch p.Err() {
        case nil:
            _, err := p.Do("SET", key, j)

            if err != nil {
                c <- err
                return
            }

            c <- nil
        default:
            c <- p.Err()
            return
        }
    }()
    return c
}

如您所见,我正在使用推荐的连接池机制(http://godoc.org/github.com/garyburd/redigo/redis#Pool)。

我在应用程序获取的每个http请求上调用这些函数。问题是:一旦应用程序开始接收请求,它就会立即抛出错误。

代码语言:javascript
复制
dial tcp 54.160.xxx.xx:yyyy: connect: cannot assign requested address

(54.160.xxx.xx:yyyy是红星的宿主)

我在redis上看到,当这种情况开始发生时,只有大约600个连接,这听起来不太像。

我试着使用poolpool设置,将其设置在1000到50K之间,但结果是一样的。

有什么想法吗?

编辑

下面是我的池初始化代码(在func init中这样做):

代码语言:javascript
复制
pool = redis.Pool{
    MaxActive:   1000, // note: I tried changing this to 50K, result the same
    Dial: func() (redis.Conn, error) {
        c, err := redis.Dial("tcp", redisHost)
        if err != nil {
            return nil, err
        }
        if _, err := c.Do("AUTH", redisPassword); err != nil {
            c.Close()
            return nil, err
        }
        return c, err
    },
}

编辑2:问题通过应用下面的答案中建议的内容来解决!

池init的新代码:

代码语言:javascript
复制
pool = redis.Pool{
    MaxActive:   500,
    MaxIdle:     500,
    IdleTimeout: 5 * time.Second,
    Dial: func() (redis.Conn, error) {
        c, err := redis.DialTimeout("tcp", redisHost, 100*time.Millisecond, 100*time.Millisecond, 100*time.Millisecond)
        if err != nil {
            return nil, err
        }
        if _, err := c.Do("AUTH", redisPassword); err != nil {
            c.Close()
            return nil, err
        }
        return c, err
    },
}

这个新的init使得get和set超时在内部由redigo处理,因此我不再需要返回getCachedVPAIDConfig和setCachedVPAIDConfig函数上的通道。他们现在的样子是这样的:

代码语言:javascript
复制
func setCachedVPAIDConfig(key string, j []byte) error {
    p := pool.Get()
    switch p.Err() {
    case nil:
        _, err := p.Do("SET", key, j)
        p.Close()
        return err
    default:
        p.Close()
        return p.Err()
    }
}

func getCachedVPAIDConfig(key string) ([]byte, error) {
    p := pool.Get()
    switch p.Err() {
    case nil:
        item, err := redis.Bytes(p.Do("GET", key))
        p.Close()
        return item, err
    default:
        p.Close()
        return nil, p.Err()
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-06-15 07:22:34

  1. 在发送通道后,您将关闭连接,如果通道阻塞,则不会关闭连接,这将导致所看到的错误。所以不要只是推迟,显式地关闭连接。
  2. 我认为这不是问题,而是一个好主意--为您与DialTimeout的连接设置一个超时。
  3. 确保您有一个正确的TestOnBorrow函数来消除死连接,特别是在超时的情况下。如果连接空闲超过3秒(函数接收空闲时间作为参数),则通常执行PING操作。
  4. 尝试将MaxIdle设置为更大的数目,我记得在池中增加该参数解决了池的问题。
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37828284

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档