Slightly pause on requests to allow most to finish

Currently, every write will result in a 202 (etcd adding a few
ms of latency to each request).  This forces clients to go into
a poll loop and pick a reasonable server poll frequency, which
results in 1 + N queries to the server for the single operation
and adds unavoidable latency to each request which affects their
perception of the service.

Add a very slight (25ms by default) delay to wait for requests
to finish.  For clients doing normal writes this reduces the
requests made against the server to 1.  For clients on long requests
this has no effect.  The downside is that http connections are held
on to for a longer period in high write loads.  The decrease in
perceived latency from the kubecfg is significant.
This commit is contained in:
Clayton Coleman 2014-07-29 09:40:40 -04:00
parent 2486414c16
commit 1bdeb058e1
3 changed files with 11 additions and 4 deletions

View File

@ -59,10 +59,11 @@ func NewNotFoundErr(kind, name string) error {
//
// TODO: consider migrating this to go-restful which is a more full-featured version of the same thing.
type APIServer struct {
prefix string
storage map[string]RESTStorage
ops *Operations
mux *http.ServeMux
prefix string
storage map[string]RESTStorage
ops *Operations
mux *http.ServeMux
asyncOpWait time.Duration
}
// New creates a new APIServer object.
@ -74,6 +75,8 @@ func New(storage map[string]RESTStorage, prefix string) *APIServer {
prefix: strings.TrimRight(prefix, "/"),
ops: NewOperations(),
mux: http.NewServeMux(),
// Delay just long enough to handle most simple write operations
asyncOpWait: time.Millisecond * 25,
}
// Primary API methods
@ -279,6 +282,8 @@ func (s *APIServer) createOperation(out <-chan interface{}, sync bool, timeout t
op := s.ops.NewOperation(out)
if sync {
op.WaitFor(timeout)
} else if s.asyncOpWait != 0 {
op.WaitFor(s.asyncOpWait)
}
return op
}

View File

@ -400,6 +400,7 @@ func TestCreate(t *testing.T) {
handler := New(map[string]RESTStorage{
"foo": simpleStorage,
}, "/prefix/version")
handler.asyncOpWait = 0
server := httptest.NewServer(handler)
client := http.Client{}

View File

@ -95,6 +95,7 @@ func TestOpGet(t *testing.T) {
handler := New(map[string]RESTStorage{
"foo": simpleStorage,
}, "/prefix/version")
handler.asyncOpWait = 0
server := httptest.NewServer(handler)
client := http.Client{}