Switch the client event recorder from exponential backoff to one random

sleep on the first failed request followed by a constant amount on all
subsequent consecutive failed requests.
This commit is contained in:
Alex Robinson 2015-01-13 19:13:24 +00:00
parent be6b1cf0e2
commit 3eaf362f8e
2 changed files with 13 additions and 16 deletions

View File

@ -18,7 +18,7 @@ package record
import ( import (
"fmt" "fmt"
"math" "math/rand"
"time" "time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
@ -26,19 +26,14 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/wait"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
"github.com/golang/glog" "github.com/golang/glog"
) )
const maxTriesPerEvent = 10 const maxTriesPerEvent = 12
var ( var sleepDuration = time.Duration(10 * time.Second)
minSleep = float64(1 * time.Second)
maxSleep = float64(15 * time.Second)
backoffExp = 1.5
)
// EventRecorder knows how to store events (client.Client implements it.) // EventRecorder knows how to store events (client.Client implements it.)
// EventRecorder must respect the namespace that will be embedded in 'event'. // EventRecorder must respect the namespace that will be embedded in 'event'.
@ -70,9 +65,13 @@ func StartRecording(recorder EventRecorder, source api.EventSource) watch.Interf
glog.Errorf("Unable to write event '%#v' (retry limit exceeded!)", event) glog.Errorf("Unable to write event '%#v' (retry limit exceeded!)", event)
break break
} }
sleepDuration := time.Duration( // Randomize the first sleep so that various clients won't all be
math.Min(maxSleep, minSleep*math.Pow(backoffExp, float64(tries-1)))) // synced up if the master goes down.
time.Sleep(wait.Jitter(sleepDuration, 0.5)) if tries == 1 {
time.Sleep(time.Duration(float64(sleepDuration) * rand.Float64()))
} else {
time.Sleep(sleepDuration)
}
} }
}) })
} }

View File

@ -22,7 +22,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"testing" "testing"
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
@ -33,8 +32,7 @@ import (
func init() { func init() {
// Don't bother sleeping between retries. // Don't bother sleeping between retries.
minSleep = 0 sleepDuration = 0
maxSleep = 0
} }
type testEventRecorder struct { type testEventRecorder struct {
@ -195,12 +193,12 @@ func TestWriteEventError(t *testing.T) {
}, },
"retry1": { "retry1": {
timesToSendError: 1000, timesToSendError: 1000,
attemptsWanted: 10, attemptsWanted: 12,
err: &errors.UnexpectedObjectError{}, err: &errors.UnexpectedObjectError{},
}, },
"retry2": { "retry2": {
timesToSendError: 1000, timesToSendError: 1000,
attemptsWanted: 10, attemptsWanted: 12,
err: fmt.Errorf("A weird error"), err: fmt.Errorf("A weird error"),
}, },
"succeedEventually": { "succeedEventually": {