forked from TrueCloudLab/frostfs-node
[#1213] morph/client: Remember last succesfully used client
Prevent attemts to connect to the failing endpoint multiple times. This speeds up all invocations a bit and removes excessive error logs. Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
9bbb136e4a
commit
923db59149
1 changed files with 24 additions and 13 deletions
|
@ -16,8 +16,11 @@ type multiClient struct {
|
||||||
sharedNotary *notary // notary config needed for single client construction
|
sharedNotary *notary // notary config needed for single client construction
|
||||||
|
|
||||||
endpoints []string
|
endpoints []string
|
||||||
clientsMtx sync.Mutex
|
clientsMtx sync.RWMutex
|
||||||
clients map[string]*Client
|
// lastSuccess is an index in endpoints array relating to a last
|
||||||
|
// used endpoint.
|
||||||
|
lastSuccess int
|
||||||
|
clients map[string]*Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// createForAddress creates single Client instance using provided endpoint.
|
// createForAddress creates single Client instance using provided endpoint.
|
||||||
|
@ -58,29 +61,32 @@ func (x *multiClient) createForAddress(addr string) (*Client, error) {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// iterateClients executes f on each client until nil error is returned.
|
||||||
|
// When nil error is returned, lastSuccess field is updated.
|
||||||
|
// The iteration order is non-deterministic and shouldn't be relied upon.
|
||||||
func (x *multiClient) iterateClients(f func(*Client) error) error {
|
func (x *multiClient) iterateClients(f func(*Client) error) error {
|
||||||
var (
|
var (
|
||||||
firstErr error
|
firstErr error
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
for i := range x.endpoints {
|
x.clientsMtx.RLock()
|
||||||
select {
|
start := x.lastSuccess
|
||||||
case <-x.cfg.ctx.Done():
|
x.clientsMtx.RUnlock()
|
||||||
return x.cfg.ctx.Err()
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
x.clientsMtx.Lock()
|
for i := 0; i < len(x.endpoints); i++ {
|
||||||
c, cached := x.clients[x.endpoints[i]]
|
index := (start + i) % len(x.endpoints)
|
||||||
x.clientsMtx.Unlock()
|
|
||||||
|
x.clientsMtx.RLock()
|
||||||
|
c, cached := x.clients[x.endpoints[index]]
|
||||||
|
x.clientsMtx.RUnlock()
|
||||||
if !cached {
|
if !cached {
|
||||||
c, err = x.createForAddress(x.endpoints[i])
|
c, err = x.createForAddress(x.endpoints[index])
|
||||||
}
|
}
|
||||||
|
|
||||||
if !cached && err != nil {
|
if !cached && err != nil {
|
||||||
x.cfg.logger.Error("could not open morph client connection",
|
x.cfg.logger.Error("could not open morph client connection",
|
||||||
zap.String("endpoint", x.endpoints[i]),
|
zap.String("endpoint", x.endpoints[index]),
|
||||||
zap.String("err", err.Error()),
|
zap.String("err", err.Error()),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -88,6 +94,11 @@ func (x *multiClient) iterateClients(f func(*Client) error) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
if i != 0 {
|
||||||
|
x.clientsMtx.Lock()
|
||||||
|
x.lastSuccess = index
|
||||||
|
x.clientsMtx.Unlock()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue