Skip to content

Commit 08d981c

Browse files
authored
Merge pull request #53 from caesarxuchao/exponential-backoff
Do exponential backoff in clientset sync
2 parents 65cfded + 2a115c2 commit 08d981c

File tree

2 files changed

+54
-35
lines changed

2 files changed

+54
-35
lines changed

cmd/agent/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func (o *GrpcProxyAgentOptions) Flags() *pflag.FlagSet {
9393
flags.StringVar(&o.proxyServerHost, "proxy-server-host", o.proxyServerHost, "The hostname to use to connect to the proxy-server.")
9494
flags.IntVar(&o.proxyServerPort, "proxy-server-port", o.proxyServerPort, "The port the proxy server is listening on.")
9595
flags.StringVar(&o.agentID, "agent-id", o.agentID, "The unique ID of this agent. Default to a generated uuid if not set.")
96-
flags.DurationVar(&o.syncInterval, "sync-interval", o.syncInterval, "The interval by which the agent periodically checks that it has connections to all instances of the proxy server.")
96+
flags.DurationVar(&o.syncInterval, "sync-interval", o.syncInterval, "The initial interval by which the agent periodically checks if it has connections to all instances of the proxy server.")
9797
flags.DurationVar(&o.probeInterval, "probe-interval", o.probeInterval, "The interval by which the agent periodically checks if its connections to the proxy server are ready.")
9898
flags.DurationVar(&o.reconnectInterval, "reconnect-interval", o.reconnectInterval, "The interval by which the agent tries to reconnect.")
9999
flags.StringVar(&o.serviceAccountTokenPath, "service-account-token-path", o.serviceAccountTokenPath, "If non-empty proxy agent uses this token to prove its identity to the proxy server.")

pkg/agent/agentclient/clientset.go

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,20 @@ package agentclient
1818

1919
import (
2020
"fmt"
21-
"math/rand"
2221
"sync"
2322
"time"
2423

2524
"google.golang.org/grpc"
2625
"google.golang.org/grpc/connectivity"
26+
"k8s.io/apimachinery/pkg/util/wait"
2727
"k8s.io/klog"
2828
)
2929

3030
// ClientSet consists of clients connected to each instance of an HA proxy server.
3131
type ClientSet struct {
3232
mu sync.Mutex //protects the clients.
3333
clients map[string]*AgentClient // map between serverID and the client
34-
// connects to this proxy server.
34+
// connects to this server.
3535

3636
agentID string // ID of this agent
3737
address string // proxy server address. Assuming HA proxy server
@@ -101,24 +101,24 @@ func (cs *ClientSet) RemoveClient(serverID string) {
101101
}
102102

103103
type ClientSetConfig struct {
104-
Address string
105-
AgentID string
106-
SyncInterval time.Duration
107-
ProbeInterval time.Duration
108-
ReconnectInterval time.Duration
109-
DialOption grpc.DialOption
104+
Address string
105+
AgentID string
106+
SyncInterval time.Duration
107+
ProbeInterval time.Duration
108+
ReconnectInterval time.Duration
109+
DialOption grpc.DialOption
110110
ServiceAccountTokenPath string
111111
}
112112

113113
func (cc *ClientSetConfig) NewAgentClientSet() *ClientSet {
114114
return &ClientSet{
115-
clients: make(map[string]*AgentClient),
116-
agentID: cc.AgentID,
117-
address: cc.Address,
118-
syncInterval: cc.SyncInterval,
119-
probeInterval: cc.ProbeInterval,
120-
reconnectInterval: cc.ReconnectInterval,
121-
dialOption: cc.DialOption,
115+
clients: make(map[string]*AgentClient),
116+
agentID: cc.AgentID,
117+
address: cc.Address,
118+
syncInterval: cc.SyncInterval,
119+
probeInterval: cc.ProbeInterval,
120+
reconnectInterval: cc.ReconnectInterval,
121+
dialOption: cc.DialOption,
122122
serviceAccountTokenPath: cc.ServiceAccountTokenPath,
123123
}
124124

@@ -128,30 +128,49 @@ func (cs *ClientSet) newAgentClient() (*AgentClient, error) {
128128
return newAgentClient(cs.address, cs.agentID, cs, cs.dialOption)
129129
}
130130

131+
func (cs *ClientSet) resetBackoff() *wait.Backoff {
132+
return &wait.Backoff{
133+
Steps: 3,
134+
Jitter: 0.1,
135+
Factor: 1.5,
136+
Duration: cs.syncInterval,
137+
Cap: 60 * time.Second,
138+
}
139+
}
140+
131141
// sync makes sure that #clients >= #proxy servers
132142
func (cs *ClientSet) sync() {
133-
jitter := float64(0.2)
143+
backoff := cs.resetBackoff()
144+
var duration time.Duration
134145
for {
135-
if cs.serverCount != 0 {
136-
sleep := cs.syncInterval + time.Duration(rand.Float64()*jitter*float64(cs.syncInterval))
137-
time.Sleep(sleep)
138-
}
139-
if cs.serverCount == 0 || cs.ClientsCount() < cs.serverCount {
140-
c, err := cs.newAgentClient()
141-
if err != nil {
142-
klog.Error(err)
143-
continue
144-
}
145-
cs.serverCount = c.stream.serverCount
146-
if err := cs.AddClient(c.stream.serverID, c); err != nil {
147-
klog.Infof("closing connection: %v", err)
148-
c.Close()
149-
continue
150-
}
151-
klog.Infof("sync added client connecting to proxy server %s", c.stream.serverID)
152-
go c.Serve()
146+
if err := cs.syncOnce(); err != nil {
147+
klog.Error(err)
148+
duration = backoff.Step()
149+
} else {
150+
backoff = cs.resetBackoff()
151+
duration = wait.Jitter(backoff.Duration, backoff.Jitter)
153152
}
153+
time.Sleep(duration)
154+
}
155+
}
156+
157+
func (cs *ClientSet) syncOnce() error {
158+
if cs.serverCount != 0 && cs.ClientsCount() >= cs.serverCount {
159+
return nil
160+
}
161+
c, err := cs.newAgentClient()
162+
if err != nil {
163+
return err
154164
}
165+
cs.serverCount = c.stream.serverCount
166+
if err := cs.AddClient(c.stream.serverID, c); err != nil {
167+
klog.Infof("closing connection: %v", err)
168+
c.Close()
169+
return nil
170+
}
171+
klog.Infof("sync added client connecting to proxy server %s", c.stream.serverID)
172+
go c.Serve()
173+
return nil
155174
}
156175

157176
func (cs *ClientSet) Serve() {

0 commit comments

Comments
 (0)