apiserver: tri-state watch cache capacity: off, default, value

This commit is contained in:
Dr. Stefan Schimanski 2017-05-05 11:21:10 +02:00
parent 1780a527f6
commit b799e62e1a
11 changed files with 68 additions and 62 deletions

View File

@ -11,10 +11,7 @@ go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["cachesize.go"], srcs = ["cachesize.go"],
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = ["//vendor/github.com/golang/glog:go_default_library"],
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
],
) )
filegroup( filegroup(

View File

@ -23,8 +23,6 @@ import (
"strings" "strings"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/apiserver/pkg/registry/generic/registry"
) )
type Resource string type Resource string
@ -111,11 +109,13 @@ func SetWatchCacheSizes(cacheSizes []string) {
} }
} }
func GetWatchCacheSizeByResource(resource string) int { // TODO this should use schema.GroupResource for lookups // GetWatchCacheSizeByResource returns the configured watch cache size for the given resource.
// A nil value means to use a default size, zero means to disable caching.
func GetWatchCacheSizeByResource(resource string) (ret *int) { // TODO this should use schema.GroupResource for lookups
if value, found := watchCacheSizes[Resource(resource)]; found { if value, found := watchCacheSizes[Resource(resource)]; found {
return value return &value
} }
return registry.DefaultWatchCacheSize return nil
} }
func maxInt(a, b int) int { func maxInt(a, b int) int {

View File

@ -40,7 +40,7 @@ func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
} }
// We explicitly do NOT do any decoration here yet. // TODO determine why we do not want to cache here // We explicitly do NOT do any decoration here yet. // TODO determine why we do not want to cache here
opts.Decorator = generic.UndecoratedStorage // TODO use watchCacheSize=-1 to signal UndecoratedStorage opts.Decorator = generic.UndecoratedStorage
store := &genericregistry.Store{ store := &genericregistry.Store{
Copier: api.Scheme, Copier: api.Scheme,

View File

@ -25,41 +25,49 @@ import (
"k8s.io/apiserver/pkg/storage/storagebackend/factory" "k8s.io/apiserver/pkg/storage/storagebackend/factory"
) )
var _ generic.StorageDecorator = StorageWithCacher
// Creates a cacher based given storageConfig. // Creates a cacher based given storageConfig.
func StorageWithCacher( func StorageWithCacher(defaultCapacity int) generic.StorageDecorator {
copier runtime.ObjectCopier, return func(
storageConfig *storagebackend.Config, copier runtime.ObjectCopier,
capacity int, storageConfig *storagebackend.Config,
objectType runtime.Object, requestedSize *int,
resourcePrefix string, objectType runtime.Object,
keyFunc func(obj runtime.Object) (string, error), resourcePrefix string,
newListFunc func() runtime.Object, keyFunc func(obj runtime.Object) (string, error),
getAttrsFunc storage.AttrFunc, newListFunc func() runtime.Object,
triggerFunc storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc) { getAttrsFunc storage.AttrFunc,
triggerFunc storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc) {
s, d := generic.NewRawStorage(storageConfig) capacity := defaultCapacity
// TODO: we would change this later to make storage always have cacher and hide low level KV layer inside. if requestedSize != nil && *requestedSize == 0 {
// Currently it has two layers of same storage interface -- cacher and low level kv. panic("StorageWithCacher must not be called with zero cache size")
cacherConfig := storage.CacherConfig{ }
CacheCapacity: capacity, if requestedSize != nil {
Storage: s, capacity = *requestedSize
Versioner: etcdstorage.APIObjectVersioner{}, }
Copier: copier,
Type: objectType,
ResourcePrefix: resourcePrefix,
KeyFunc: keyFunc,
NewListFunc: newListFunc,
GetAttrsFunc: getAttrsFunc,
TriggerPublisherFunc: triggerFunc,
Codec: storageConfig.Codec,
}
cacher := storage.NewCacherFromConfig(cacherConfig)
destroyFunc := func() {
cacher.Stop()
d()
}
return cacher, destroyFunc s, d := generic.NewRawStorage(storageConfig)
// TODO: we would change this later to make storage always have cacher and hide low level KV layer inside.
// Currently it has two layers of same storage interface -- cacher and low level kv.
cacherConfig := storage.CacherConfig{
CacheCapacity: capacity,
Storage: s,
Versioner: etcdstorage.APIObjectVersioner{},
Copier: copier,
Type: objectType,
ResourcePrefix: resourcePrefix,
KeyFunc: keyFunc,
NewListFunc: newListFunc,
GetAttrsFunc: getAttrsFunc,
TriggerPublisherFunc: triggerFunc,
Codec: storageConfig.Codec,
}
cacher := storage.NewCacherFromConfig(cacherConfig)
destroyFunc := func() {
cacher.Stop()
d()
}
return cacher, destroyFunc
}
} }

View File

@ -44,9 +44,6 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
) )
// defaultWatchCacheSize is the default size of a watch catch per resource in number of entries.
const DefaultWatchCacheSize = 100
// ObjectFunc is a function to act on a given object. An error may be returned // ObjectFunc is a function to act on a given object. An error may be returned
// if the hook cannot be completed. An ObjectFunc may transform the provided // if the hook cannot be completed. An ObjectFunc may transform the provided
// object. // object.
@ -164,9 +161,9 @@ type Store struct {
// Called to cleanup clients used by the underlying Storage; optional. // Called to cleanup clients used by the underlying Storage; optional.
DestroyFunc func() DestroyFunc func()
// Maximum size of the watch history cached in memory, in number of entries. // Maximum size of the watch history cached in memory, in number of entries.
// A zero value here means that a default is used. This value is ignored if // This value is ignored if Storage is non-nil. Nil is replaced with a default value.
// Storage is non-nil. // A zero integer will disable caching.
WatchCacheSize int WatchCacheSize *int
} }
// Note: the rest.StandardStorage interface aggregates the common REST verbs // Note: the rest.StandardStorage interface aggregates the common REST verbs
@ -1205,14 +1202,10 @@ func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error {
} }
if e.Storage == nil { if e.Storage == nil {
capacity := DefaultWatchCacheSize
if e.WatchCacheSize != 0 {
capacity = e.WatchCacheSize
}
e.Storage, e.DestroyFunc = opts.Decorator( e.Storage, e.DestroyFunc = opts.Decorator(
e.Copier, e.Copier,
opts.StorageConfig, opts.StorageConfig,
capacity, e.WatchCacheSize,
e.NewFunc(), e.NewFunc(),
prefix, prefix,
keyFunc, keyFunc,

View File

@ -26,10 +26,11 @@ import (
// StorageDecorator is a function signature for producing a storage.Interface // StorageDecorator is a function signature for producing a storage.Interface
// and an associated DestroyFunc from given parameters. // and an associated DestroyFunc from given parameters.
// A zero capacity means to disable caching, nil means to use a default.
type StorageDecorator func( type StorageDecorator func(
copier runtime.ObjectCopier, copier runtime.ObjectCopier,
config *storagebackend.Config, config *storagebackend.Config,
capacity int, capacity *int,
objectType runtime.Object, objectType runtime.Object,
resourcePrefix string, resourcePrefix string,
keyFunc func(obj runtime.Object) (string, error), keyFunc func(obj runtime.Object) (string, error),
@ -42,7 +43,7 @@ type StorageDecorator func(
func UndecoratedStorage( func UndecoratedStorage(
copier runtime.ObjectCopier, copier runtime.ObjectCopier,
config *storagebackend.Config, config *storagebackend.Config,
capacity int, capacity *int,
objectType runtime.Object, objectType runtime.Object,
resourcePrefix string, resourcePrefix string,
keyFunc func(obj runtime.Object) (string, error), keyFunc func(obj runtime.Object) (string, error),

View File

@ -39,7 +39,11 @@ type EtcdOptions struct {
DefaultStorageMediaType string DefaultStorageMediaType string
DeleteCollectionWorkers int DeleteCollectionWorkers int
EnableGarbageCollection bool EnableGarbageCollection bool
EnableWatchCache bool
// Set EnableWatchCache to false to disable all watch caches
EnableWatchCache bool
// Set DefaultWatchCacheSize to zero to disable watch caches for those resources that have no explicit cache size set
DefaultWatchCacheSize int
} }
func NewEtcdOptions(backendConfig *storagebackend.Config) *EtcdOptions { func NewEtcdOptions(backendConfig *storagebackend.Config) *EtcdOptions {
@ -49,6 +53,7 @@ func NewEtcdOptions(backendConfig *storagebackend.Config) *EtcdOptions {
DeleteCollectionWorkers: 1, DeleteCollectionWorkers: 1,
EnableGarbageCollection: true, EnableGarbageCollection: true,
EnableWatchCache: true, EnableWatchCache: true,
DefaultWatchCacheSize: 100,
} }
} }
@ -129,7 +134,7 @@ func (f *SimpleRestOptionsFactory) GetRESTOptions(resource schema.GroupResource)
ResourcePrefix: f.Options.StorageConfig.Prefix + "/" + resource.Group + "/" + resource.Resource, ResourcePrefix: f.Options.StorageConfig.Prefix + "/" + resource.Group + "/" + resource.Resource,
} }
if f.Options.EnableWatchCache { if f.Options.EnableWatchCache {
ret.Decorator = genericregistry.StorageWithCacher ret.Decorator = genericregistry.StorageWithCacher(f.Options.DefaultWatchCacheSize)
} }
return ret, nil return ret, nil
} }
@ -153,7 +158,7 @@ func (f *storageFactoryRestOptionsFactory) GetRESTOptions(resource schema.GroupR
ResourcePrefix: f.StorageFactory.ResourcePrefix(resource), ResourcePrefix: f.StorageFactory.ResourcePrefix(resource),
} }
if f.Options.EnableWatchCache { if f.Options.EnableWatchCache {
ret.Decorator = genericregistry.StorageWithCacher ret.Decorator = genericregistry.StorageWithCacher(f.Options.DefaultWatchCacheSize)
} }
return ret, nil return ret, nil

View File

@ -38,7 +38,6 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) *REST
NewListFunc: func() runtime.Object { return &apiregistration.APIServiceList{} }, NewListFunc: func() runtime.Object { return &apiregistration.APIServiceList{} },
PredicateFunc: apiservice.MatchAPIService, PredicateFunc: apiservice.MatchAPIService,
QualifiedResource: apiregistration.Resource("apiservices"), QualifiedResource: apiregistration.Resource("apiservices"),
WatchCacheSize: 100,
CreateStrategy: strategy, CreateStrategy: strategy,
UpdateStrategy: strategy, UpdateStrategy: strategy,

View File

@ -353,6 +353,7 @@ type CustomResourceRESTOptionsGetter struct {
StorageConfig storagebackend.Config StorageConfig storagebackend.Config
StoragePrefix string StoragePrefix string
EnableWatchCache bool EnableWatchCache bool
DefaultWatchCacheSize int
EnableGarbageCollection bool EnableGarbageCollection bool
DeleteCollectionWorkers int DeleteCollectionWorkers int
} }
@ -366,7 +367,7 @@ func (t CustomResourceRESTOptionsGetter) GetRESTOptions(resource schema.GroupRes
ResourcePrefix: t.StoragePrefix + "/" + resource.Group + "/" + resource.Resource, ResourcePrefix: t.StoragePrefix + "/" + resource.Group + "/" + resource.Resource,
} }
if t.EnableWatchCache { if t.EnableWatchCache {
ret.Decorator = genericregistry.StorageWithCacher ret.Decorator = genericregistry.StorageWithCacher(t.DefaultWatchCacheSize)
} }
return ret, nil return ret, nil
} }

View File

@ -99,6 +99,7 @@ func (o CustomResourcesServerOptions) Config() (*apiserver.Config, error) {
StorageConfig: o.RecommendedOptions.Etcd.StorageConfig, StorageConfig: o.RecommendedOptions.Etcd.StorageConfig,
StoragePrefix: o.RecommendedOptions.Etcd.StorageConfig.Prefix, StoragePrefix: o.RecommendedOptions.Etcd.StorageConfig.Prefix,
EnableWatchCache: o.RecommendedOptions.Etcd.EnableWatchCache, EnableWatchCache: o.RecommendedOptions.Etcd.EnableWatchCache,
DefaultWatchCacheSize: o.RecommendedOptions.Etcd.DefaultWatchCacheSize,
EnableGarbageCollection: o.RecommendedOptions.Etcd.EnableGarbageCollection, EnableGarbageCollection: o.RecommendedOptions.Etcd.EnableGarbageCollection,
DeleteCollectionWorkers: o.RecommendedOptions.Etcd.DeleteCollectionWorkers, DeleteCollectionWorkers: o.RecommendedOptions.Etcd.DeleteCollectionWorkers,
} }

View File

@ -80,6 +80,7 @@ func DefaultServerConfig() (*extensionsapiserver.Config, error) {
StorageConfig: options.RecommendedOptions.Etcd.StorageConfig, StorageConfig: options.RecommendedOptions.Etcd.StorageConfig,
StoragePrefix: options.RecommendedOptions.Etcd.StorageConfig.Prefix, StoragePrefix: options.RecommendedOptions.Etcd.StorageConfig.Prefix,
EnableWatchCache: options.RecommendedOptions.Etcd.EnableWatchCache, EnableWatchCache: options.RecommendedOptions.Etcd.EnableWatchCache,
DefaultWatchCacheSize: options.RecommendedOptions.Etcd.DefaultWatchCacheSize,
EnableGarbageCollection: options.RecommendedOptions.Etcd.EnableGarbageCollection, EnableGarbageCollection: options.RecommendedOptions.Etcd.EnableGarbageCollection,
DeleteCollectionWorkers: options.RecommendedOptions.Etcd.DeleteCollectionWorkers, DeleteCollectionWorkers: options.RecommendedOptions.Etcd.DeleteCollectionWorkers,
} }