Adds client and transport pooling in the API so we don't leak connections.

This commit is contained in:
James Phillips 2015-12-16 22:27:07 -08:00
parent 3b455787a6
commit d57e60a123
2 changed files with 40 additions and 21 deletions

View File

@ -13,6 +13,7 @@ import (
"os" "os"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
"github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/go-cleanhttp"
@ -122,12 +123,20 @@ type Config struct {
Token string Token string
} }
var defaultHttpClient = cleanhttp.DefaultClient()
var defaultInsecureTransport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
// DefaultConfig returns a default configuration for the client // DefaultConfig returns a default configuration for the client
func DefaultConfig() *Config { func DefaultConfig() *Config {
config := &Config{ config := &Config{
Address: "127.0.0.1:8500", Address: "127.0.0.1:8500",
Scheme: "http", Scheme: "http",
HttpClient: cleanhttp.DefaultClient(), HttpClient: defaultHttpClient,
} }
if addr := os.Getenv("CONSUL_HTTP_ADDR"); addr != "" { if addr := os.Getenv("CONSUL_HTTP_ADDR"); addr != "" {
@ -172,11 +181,7 @@ func DefaultConfig() *Config {
} }
if !doVerify { if !doVerify {
config.HttpClient.Transport = &http.Transport{ config.HttpClient.Transport = defaultInsecureTransport
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
} }
} }
@ -188,6 +193,9 @@ type Client struct {
config Config config Config
} }
var unixClients = make(map[string]*http.Client)
var unixClientsLock sync.Mutex
// NewClient returns a new client // NewClient returns a new client
func NewClient(config *Config) (*Client, error) { func NewClient(config *Config) (*Client, error) {
// bootstrap the config // bootstrap the config
@ -206,14 +214,22 @@ func NewClient(config *Config) (*Client, error) {
} }
if parts := strings.SplitN(config.Address, "unix://", 2); len(parts) == 2 { if parts := strings.SplitN(config.Address, "unix://", 2); len(parts) == 2 {
trans := cleanhttp.DefaultTransport()
trans.Dial = func(_, _ string) (net.Conn, error) {
return net.Dial("unix", parts[1])
}
config.HttpClient = &http.Client{
Transport: trans,
}
config.Address = parts[1] config.Address = parts[1]
unixClientsLock.Lock()
if client, ok := unixClients[config.Address]; ok {
config.HttpClient = client
} else {
trans := cleanhttp.DefaultTransport()
trans.Dial = func(_, _ string) (net.Conn, error) {
return net.Dial("unix", config.Address)
}
config.HttpClient = &http.Client{
Transport: trans,
}
unixClients[config.Address] = config.HttpClient
}
unixClientsLock.Unlock()
} }
client := &Client{ client := &Client{

View File

@ -244,13 +244,16 @@ func TestAPI_UnixSocket(t *testing.T) {
}) })
defer s.Stop() defer s.Stop()
agent := c.Agent() // Run a few iterations to test the path where we use the pooled
// connection.
info, err := agent.Self() for i := 0; i < 3; i++ {
if err != nil { agent := c.Agent()
t.Fatalf("err: %s", err) info, err := agent.Self()
} if err != nil {
if info["Config"]["NodeName"] == "" { t.Fatalf("err: %s", err)
t.Fatalf("bad: %v", info) }
if info["Config"]["NodeName"] == "" {
t.Fatalf("bad: %v", info)
}
} }
} }