-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.go
92 lines (81 loc) · 2.26 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package fhlbclient
import (
"errors"
"sync"
"time"
"github.com/valyala/fasthttp"
)
const (
DefaultTimeout = time.Second
DefaultPenalty = time.Second * 3
)
// Load balancing client.
//
// See https://github.com/valyala/fasthttp/blob/master/lbclient.go for details and comparison.
type LBClient struct {
// Array of clients to balance.
Clients []fasthttp.BalancingClient
// Health check helper.
HealthCheck HealthChecker
// Timeout duration to execute request.
// Will used DefaultTimeout if empty.
Timeout time.Duration
// Penalty duration to ban the client.
Penalty time.Duration
// Balancer helper.
Balancer Balancer
// Request hooks helper.
RequestHooker RequestHooker
// Array of wrappers around Clients.
// Note, that Clients used only for init step and copies into cln.
cln []PenalizingClient
once sync.Once
}
var ErrNoAliveClients = errors.New("no alive clients available")
// Init the load balancing client.
func (c *LBClient) init() {
// Get penalty duration.
pd := c.Penalty
if pd <= 0 {
pd = DefaultPenalty
}
// Check balancer helper.
if c.Balancer == nil {
c.Balancer = &DummyBalancer{}
}
// Check request hooks helper.
if c.RequestHooker == nil {
c.RequestHooker = &DummyRequestHooks{}
}
// Make new PenalizingClient for each provided BalancingClient.
c.cln = make([]PenalizingClient, 0, len(c.Clients))
for _, bc := range c.Clients {
c.cln = append(c.cln, PenalizingClient{
bc: bc,
hc: c.HealthCheck,
pd: pd,
})
}
}
// Execute request with given deadline.
func (c *LBClient) DoDeadline(req *fasthttp.Request, resp *fasthttp.Response, deadline time.Time) error {
return c.DoDeadlineWB(req, resp, deadline, c.Balancer)
}
// Execute request with given timeout.
func (c *LBClient) DoTimeout(req *fasthttp.Request, resp *fasthttp.Response, timeout time.Duration) error {
return c.DoTimeoutWB(req, resp, timeout, c.Balancer)
}
// Execute request with internal timeout.
func (c *LBClient) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
return c.DoWB(req, resp, c.Balancer)
}
// Get least loaded client.
func (c *LBClient) get(b Balancer) *PenalizingClient {
// Run init() once.
c.once.Do(c.init)
if len(c.cln) == 0 || b == nil {
return nil
}
// Use balancer helper to get best candidate.
return b.Evaluate(c.cln)
}