mirror of
https://github.com/yusing/godoxy.git
synced 2025-05-20 12:42:34 +02:00
reduce docker client initiation
This commit is contained in:
parent
a3e705373c
commit
357ad26a0e
1 changed files with 55 additions and 25 deletions
|
@ -4,14 +4,13 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/connhelper"
|
"github.com/docker/cli/cli/connhelper"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/rs/zerolog"
|
|
||||||
"github.com/yusing/go-proxy/internal/common"
|
"github.com/yusing/go-proxy/internal/common"
|
||||||
"github.com/yusing/go-proxy/internal/logging"
|
"github.com/yusing/go-proxy/internal/logging"
|
||||||
"github.com/yusing/go-proxy/internal/task"
|
"github.com/yusing/go-proxy/internal/task"
|
||||||
U "github.com/yusing/go-proxy/internal/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -19,15 +18,14 @@ type (
|
||||||
*client.Client
|
*client.Client
|
||||||
|
|
||||||
key string
|
key string
|
||||||
refCount *U.RefCount
|
refCount uint32
|
||||||
|
closedOn int64
|
||||||
l zerolog.Logger
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
clientMap = make(map[string]*SharedClient, 5)
|
clientMap = make(map[string]*SharedClient, 5)
|
||||||
clientMapMu sync.Mutex
|
clientMapMu sync.RWMutex
|
||||||
|
|
||||||
clientOptEnvHost = []client.Opt{
|
clientOptEnvHost = []client.Opt{
|
||||||
client.WithHostFromEnv(),
|
client.WithHostFromEnv(),
|
||||||
|
@ -35,12 +33,34 @@ var (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
cleanInterval = 10 * time.Second
|
||||||
|
clientTTLSecs = int64(10)
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
cleaner := task.RootTask("docker_clients_cleaner")
|
||||||
|
go func() {
|
||||||
|
ticker := time.NewTicker(cleanInterval)
|
||||||
|
defer ticker.Stop()
|
||||||
|
defer cleaner.Finish("program exit")
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
closeTimedOutClients()
|
||||||
|
case <-cleaner.Context().Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
task.OnProgramExit("docker_clients_cleanup", func() {
|
task.OnProgramExit("docker_clients_cleanup", func() {
|
||||||
clientMapMu.Lock()
|
clientMapMu.Lock()
|
||||||
defer clientMapMu.Unlock()
|
defer clientMapMu.Unlock()
|
||||||
|
|
||||||
for _, c := range clientMap {
|
for _, c := range clientMap {
|
||||||
|
delete(clientMap, c.key)
|
||||||
if c.Connected() {
|
if c.Connected() {
|
||||||
c.Client.Close()
|
c.Client.Close()
|
||||||
}
|
}
|
||||||
|
@ -48,15 +68,36 @@ func init() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func closeTimedOutClients() {
|
||||||
|
clientMapMu.Lock()
|
||||||
|
defer clientMapMu.Unlock()
|
||||||
|
|
||||||
|
now := time.Now().Unix()
|
||||||
|
|
||||||
|
for _, c := range clientMap {
|
||||||
|
if !c.Connected() {
|
||||||
|
delete(clientMap, c.key)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if c.closedOn == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if c.refCount == 0 && now-c.closedOn > clientTTLSecs {
|
||||||
|
delete(clientMap, c.key)
|
||||||
|
c.Client.Close()
|
||||||
|
logging.Debug().Str("host", c.key).Msg("docker client closed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *SharedClient) Connected() bool {
|
func (c *SharedClient) Connected() bool {
|
||||||
return c != nil && c.Client != nil
|
return c != nil && c.Client != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the client is still referenced, this is no-op.
|
// if the client is still referenced, this is no-op.
|
||||||
func (c *SharedClient) Close() {
|
func (c *SharedClient) Close() {
|
||||||
if c.Connected() {
|
c.closedOn = time.Now().Unix()
|
||||||
c.refCount.Sub()
|
c.refCount--
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnectClient creates a new Docker client connection to the specified host.
|
// ConnectClient creates a new Docker client connection to the specified host.
|
||||||
|
@ -74,7 +115,8 @@ func ConnectClient(host string) (*SharedClient, error) {
|
||||||
defer clientMapMu.Unlock()
|
defer clientMapMu.Unlock()
|
||||||
|
|
||||||
if client, ok := clientMap[host]; ok {
|
if client, ok := clientMap[host]; ok {
|
||||||
client.refCount.Add()
|
client.closedOn = 0
|
||||||
|
client.refCount++
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,23 +161,11 @@ func ConnectClient(host string) (*SharedClient, error) {
|
||||||
c := &SharedClient{
|
c := &SharedClient{
|
||||||
Client: client,
|
Client: client,
|
||||||
key: host,
|
key: host,
|
||||||
refCount: U.NewRefCounter(),
|
refCount: 1,
|
||||||
l: logging.With().Str("address", client.DaemonHost()).Logger(),
|
|
||||||
}
|
}
|
||||||
c.l.Trace().Msg("client connected")
|
|
||||||
|
|
||||||
clientMap[host] = c
|
defer logging.Debug().Str("host", host).Msg("docker client connected")
|
||||||
|
|
||||||
go func() {
|
clientMap[c.key] = c
|
||||||
<-c.refCount.Zero()
|
|
||||||
clientMapMu.Lock()
|
|
||||||
delete(clientMap, c.key)
|
|
||||||
clientMapMu.Unlock()
|
|
||||||
|
|
||||||
if c.Connected() {
|
|
||||||
c.Client.Close()
|
|
||||||
c.l.Trace().Msg("client closed")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue