title: redigo: getting dial tcp: connect: cannot assign requested address
body: <p>I have an application that makes about 400 reads per seconds and 100 writes per second to redis (hosted on redislabs). The application is using <code>github.com/garyburd/redigo</code> package as a redis proxy. </p>
  
  <p>I have two functions which are the only ones being used to read and write:</p>
  
  <pre><code>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 &lt;- &amp;cachedVPAIDConfig{nil, err}
                  return
              }
  
              c &lt;- &amp;cachedVPAIDConfig{item, nil}
          default:
              c &lt;- &amp;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 &lt;- err
                  return
              }
  
              c &lt;- nil
          default:
              c &lt;- p.Err()
              return
          }
      }()
      return c
  }
  </code></pre>
  
  <p>As you can see, I'm using the recommended connection pooling mechanism (<a href="http://godoc.org/github.com/garyburd/redigo/redis#Pool" rel="nofollow">http://godoc.org/github.com/garyburd/redigo/redis#Pool</a>). </p>
  
  <p>I'm calling these functions on every http request an endpoint on the application is getting. The problem is: once the application starts getting requests, it immediately starts throwing the error</p>
  
  <pre><code>dial tcp 54.160.xxx.xx:yyyy: connect: cannot assign requested address
  </code></pre>
  
  <p>(54.160.xxx.xx:yyyy is the redis host)</p>
  
  <p>I see on redis that there are only about 600 connections when this starts to happen, which doesn't sound like a lot.</p>
  
  <p>I tried playing with the <code>MaxActive</code> setting of the <code>pool</code>, setting it anywhere between 1000 and 50K, but the result is the same. </p>
  
  <p>Any ideas?</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>Here's my pool initialization code (doing this in <code>func init</code>):</p>
  
  <pre><code>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
      },
  }
  </code></pre>
  
  <p><strong>Edit 2:</strong>
  Issue solved by applying the stuff suggested in the answer below! </p>
  
  <p>New code for pool init:</p>
  
  <pre><code>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
      },
  }
  </code></pre>
  
  <p>This new init makes it so that the get and set timeouts are handled by redigo internally, so I no longer need to return a channel on the getCachedVPAIDConfig and setCachedVPAIDConfig funcs. This is how they look now:</p>
  
  <pre><code>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()
      }
  }
  </code></pre>