Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified bin/goaround
Binary file not shown.
2 changes: 1 addition & 1 deletion bin/shasum
Original file line number Diff line number Diff line change
@@ -1 +1 @@
f875002d695a5726444d6a86644f35449f844d44 ./bin/goaround
71711d3d03e824ec9a51ac734c94648e9874292f ./bin/goaround
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ module github.com/CoderCookE/goaround

go 1.12

require github.com/dgraph-io/ristretto v0.0.0-20191004195602-f823dc4a5031
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgraph-io/ristretto v0.0.1
github.com/stretchr/testify v1.3.0 // indirect
)
12 changes: 10 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
github.com/codercooke/goaround v0.0.0-20190726005525-216236838df3 h1:SH0qcVMNgZgsuUM8/xtmBtigM4UBvoCfuCQqsWBMo58=
github.com/codercooke/goaround v0.0.0-20190726005525-216236838df3/go.mod h1:l53nwp2tMBWyIWF0fHoVLBj5tKcovj0yC4LNp3CrvAY=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgraph-io/ristretto v0.0.0-20191004195602-f823dc4a5031 h1:puinfjvl1jM3YaODRJ63nURwCuY+7r2gaOxE4ON+68E=
github.com/dgraph-io/ristretto v0.0.0-20191004195602-f823dc4a5031/go.mod h1:jg4yDfbNNmxP2Nq5Z7MbyQrXyl/syIRF2LnbbxqViho=
github.com/dgraph-io/ristretto v0.0.1 h1:cJwdnj42uV8Jg4+KLrYovLiCgIfz9wtWm6E6KA+1tLs=
github.com/dgraph-io/ristretto v0.0.1/go.mod h1:T40EBc7CJke8TkpiYfGGKAeFjSaxuFXhuXRyumBd6RE=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
24 changes: 20 additions & 4 deletions internal/connectionpool/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ import (
"sync"
)

type message struct {
health bool
backend string
proxy *httputil.ReverseProxy
}

type connection struct {
healthy bool
messages chan bool
messages chan message
backend string
sync.RWMutex
proxy *httputil.ReverseProxy
Expand All @@ -20,7 +26,7 @@ type connection struct {
func newConnection(proxy *httputil.ReverseProxy, backend string, cache *ristretto.Cache) (*connection, error) {
conn := &connection{
backend: backend,
messages: make(chan bool),
messages: make(chan message),
proxy: proxy,
cache: cache,
}
Expand Down Expand Up @@ -56,9 +62,19 @@ func (c *connection) get(w http.ResponseWriter, r *http.Request) error {

func (c *connection) healthCheck() {
for {
healthy := <-c.messages
msg := <-c.messages

c.Lock()
c.healthy = healthy

backend := msg.backend
c.healthy = msg.health
proxy := msg.proxy

if proxy != nil && c.backend != backend {
c.backend = backend
c.proxy = proxy
}

c.Unlock()
}
}
4 changes: 2 additions & 2 deletions internal/connectionpool/connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ func TestHealthCheck(t *testing.T) {
assertion.Equal(err, nil)

assertion.False(conn.healthy)
conn.messages <- true
conn.messages <- message{health: true}
time.Sleep(200 * time.Millisecond)

conn.Lock()
health := conn.healthy
conn.Unlock()
assertion.True(health)

conn.messages <- false
conn.messages <- message{health: false}
time.Sleep(200 * time.Millisecond)

conn.Lock()
Expand Down
37 changes: 31 additions & 6 deletions internal/connectionpool/health-checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"sync"
"time"
)

Expand All @@ -16,7 +18,8 @@ type healthCheckReponse struct {
}

type healthChecker struct {
subscribers []chan bool
sync.Mutex
subscribers []chan message
currentHealth bool
client *http.Client
backend string
Expand All @@ -27,27 +30,44 @@ func (hc *healthChecker) Start() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

hc.Lock()
hc.check(ctx)
hc.Unlock()

ticker := time.NewTicker(1000 * time.Millisecond)
for {
select {
case <-ticker.C:
cancel()
hc.Lock()
ctx, cancel = context.WithCancel(context.Background())
hc.check(ctx)
hc.Unlock()
case <-hc.done:
ticker.Stop()
return
}
}
}

func (hc *healthChecker) Reuse(newBackend string, proxy *httputil.ReverseProxy) *healthChecker {
hc.Lock()
hc.backend = newBackend
hc.notifySubscribers(false, hc.backend, proxy)
hc.Unlock()

return hc
}

func (hc *healthChecker) check(ctx context.Context) {
url := fmt.Sprintf("%s%s", hc.backend, "/health")
healthy := hc.currentHealth

req, _ := http.NewRequest(http.MethodGet, url, nil)
if resp, err := http.DefaultClient.Do(req.WithContext(ctx)); err != nil {
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
log.Printf("Error creating request: %s, error %s", hc.backend, err.Error())
healthy = false
} else if resp, err := http.DefaultClient.Do(req.WithContext(ctx)); err != nil {
log.Printf("Error with health check, backend: %s, error %s", hc.backend, err.Error())
healthy = false
} else {
Expand All @@ -67,9 +87,14 @@ func (hc *healthChecker) check(ctx context.Context) {

if healthy != hc.currentHealth {
hc.currentHealth = healthy
for _, c := range hc.subscribers {
c <- healthy
}
hc.notifySubscribers(healthy, hc.backend, nil)
}
}

func (hc *healthChecker) notifySubscribers(healthy bool, backend string, proxy *httputil.ReverseProxy) {
message := message{health: healthy, backend: backend, proxy: proxy}
for _, c := range hc.subscribers {
c <- message
}
}

Expand Down
12 changes: 6 additions & 6 deletions internal/connectionpool/health-checker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestHealthChecker(t *testing.T) {
assertion := &assert.Asserter{T: t}

t.Run("backend returns a healthy state", func(t *testing.T) {
resChan := make(chan bool, 1)
resChan := make(chan message, 1)

availableHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
healthReponse := &healthCheckReponse{State: "healthy", Message: ""}
Expand All @@ -33,7 +33,7 @@ func TestHealthChecker(t *testing.T) {

hc := healthChecker{
client: client,
subscribers: []chan bool{resChan},
subscribers: []chan message{resChan},
backend: availableServer.URL,
done: make(chan bool),
currentHealth: false,
Expand All @@ -44,11 +44,11 @@ func TestHealthChecker(t *testing.T) {

health := <-resChan

assertion.True(health)
assertion.True(health.health)
})

t.Run("backend returns a degraded state", func(t *testing.T) {
resChan := make(chan bool, 1)
resChan := make(chan message, 1)

degradedHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
healthReponse := &healthCheckReponse{State: "degraded", Message: ""}
Expand All @@ -61,7 +61,7 @@ func TestHealthChecker(t *testing.T) {

hc := healthChecker{
client: client,
subscribers: []chan bool{resChan},
subscribers: []chan message{resChan},
backend: degradedServer.URL,
done: make(chan bool),
currentHealth: true,
Expand All @@ -72,6 +72,6 @@ func TestHealthChecker(t *testing.T) {

health := <-resChan

assertion.False(health)
assertion.False(health.health)
})
}
Loading