mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #4901 from heyitsanthony/config-dbsize
etcdserver: configurable backend size quota
This commit is contained in:
commit
2deed74494
@ -123,6 +123,7 @@ type config struct {
|
|||||||
printVersion bool
|
printVersion bool
|
||||||
|
|
||||||
autoCompactionRetention int
|
autoCompactionRetention int
|
||||||
|
quotaBackendBytes int64
|
||||||
|
|
||||||
enablePprof bool
|
enablePprof bool
|
||||||
|
|
||||||
@ -224,6 +225,7 @@ func NewConfig() *config {
|
|||||||
|
|
||||||
// demo flag
|
// demo flag
|
||||||
fs.IntVar(&cfg.autoCompactionRetention, "experimental-auto-compaction-retention", 0, "Auto compaction retention in hour. 0 means disable auto compaction.")
|
fs.IntVar(&cfg.autoCompactionRetention, "experimental-auto-compaction-retention", 0, "Auto compaction retention in hour. 0 means disable auto compaction.")
|
||||||
|
fs.Int64Var(&cfg.quotaBackendBytes, "quota-backend-bytes", 0, "Raise alarms when backend size exceeds the given quota. 0 means use the default quota.")
|
||||||
|
|
||||||
// backwards-compatibility with v0.4.6
|
// backwards-compatibility with v0.4.6
|
||||||
fs.Var(&flags.IPAddressPort{}, "addr", "DEPRECATED: Use --advertise-client-urls instead.")
|
fs.Var(&flags.IPAddressPort{}, "addr", "DEPRECATED: Use --advertise-client-urls instead.")
|
||||||
|
@ -347,6 +347,7 @@ func startEtcd(cfg *config) (<-chan struct{}, error) {
|
|||||||
TickMs: cfg.TickMs,
|
TickMs: cfg.TickMs,
|
||||||
ElectionTicks: cfg.electionTicks(),
|
ElectionTicks: cfg.electionTicks(),
|
||||||
AutoCompactionRetention: cfg.autoCompactionRetention,
|
AutoCompactionRetention: cfg.autoCompactionRetention,
|
||||||
|
QuotaBackendBytes: cfg.quotaBackendBytes,
|
||||||
StrictReconfigCheck: cfg.strictReconfigCheck,
|
StrictReconfigCheck: cfg.strictReconfigCheck,
|
||||||
EnablePprof: cfg.enablePprof,
|
EnablePprof: cfg.enablePprof,
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,7 @@ type ServerConfig struct {
|
|||||||
BootstrapTimeout time.Duration
|
BootstrapTimeout time.Duration
|
||||||
|
|
||||||
AutoCompactionRetention int
|
AutoCompactionRetention int
|
||||||
|
QuotaBackendBytes int64
|
||||||
|
|
||||||
StrictReconfigCheck bool
|
StrictReconfigCheck bool
|
||||||
|
|
||||||
|
@ -31,6 +31,12 @@ type Quota interface {
|
|||||||
Remaining() int64
|
Remaining() int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type passthroughQuota struct{}
|
||||||
|
|
||||||
|
func (*passthroughQuota) Available(interface{}) bool { return true }
|
||||||
|
func (*passthroughQuota) Cost(interface{}) int { return 0 }
|
||||||
|
func (*passthroughQuota) Remaining() int64 { return 1 }
|
||||||
|
|
||||||
type backendQuota struct {
|
type backendQuota struct {
|
||||||
s *EtcdServer
|
s *EtcdServer
|
||||||
maxBackendBytes int64
|
maxBackendBytes int64
|
||||||
@ -44,7 +50,20 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func NewBackendQuota(s *EtcdServer) Quota {
|
func NewBackendQuota(s *EtcdServer) Quota {
|
||||||
return &backendQuota{s, backend.InitialMmapSize}
|
if s.cfg.QuotaBackendBytes < 0 {
|
||||||
|
// disable quotas if negative
|
||||||
|
plog.Warningf("disabling backend quota")
|
||||||
|
return &passthroughQuota{}
|
||||||
|
}
|
||||||
|
if s.cfg.QuotaBackendBytes == 0 {
|
||||||
|
// use default size if no quota size given
|
||||||
|
return &backendQuota{s, backend.DefaultQuotaBytes}
|
||||||
|
}
|
||||||
|
if s.cfg.QuotaBackendBytes > backend.MaxQuotaBytes {
|
||||||
|
plog.Warningf("backend quota %v exceeds maximum quota %v; using maximum", s.cfg.QuotaBackendBytes, backend.MaxQuotaBytes)
|
||||||
|
return &backendQuota{s, backend.MaxQuotaBytes}
|
||||||
|
}
|
||||||
|
return &backendQuota{s, s.cfg.QuotaBackendBytes}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *backendQuota) Available(v interface{}) bool {
|
func (b *backendQuota) Available(v interface{}) bool {
|
||||||
|
@ -24,7 +24,6 @@ import (
|
|||||||
"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
|
"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
|
||||||
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||||
"github.com/coreos/etcd/pkg/testutil"
|
"github.com/coreos/etcd/pkg/testutil"
|
||||||
"github.com/coreos/etcd/storage/backend"
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
@ -461,16 +460,16 @@ func TestV3Hash(t *testing.T) {
|
|||||||
|
|
||||||
// TestV3StorageQuotaAPI tests the V3 server respects quotas at the API layer
|
// TestV3StorageQuotaAPI tests the V3 server respects quotas at the API layer
|
||||||
func TestV3StorageQuotaAPI(t *testing.T) {
|
func TestV3StorageQuotaAPI(t *testing.T) {
|
||||||
oldSize := backend.InitialMmapSize
|
defer testutil.AfterTest(t)
|
||||||
defer func() {
|
|
||||||
backend.InitialMmapSize = oldSize
|
|
||||||
testutil.AfterTest(t)
|
|
||||||
}()
|
|
||||||
|
|
||||||
backend.InitialMmapSize = 64 * 1024
|
|
||||||
clus := NewClusterV3(t, &ClusterConfig{Size: 3})
|
clus := NewClusterV3(t, &ClusterConfig{Size: 3})
|
||||||
|
|
||||||
|
clus.Members[0].QuotaBackendBytes = 64 * 1024
|
||||||
|
clus.Members[0].Stop(t)
|
||||||
|
clus.Members[0].Restart(t)
|
||||||
|
|
||||||
defer clus.Terminate(t)
|
defer clus.Terminate(t)
|
||||||
kvc := toGRPC(clus.RandClient()).KV
|
kvc := toGRPC(clus.Client(0)).KV
|
||||||
|
|
||||||
key := []byte("abc")
|
key := []byte("abc")
|
||||||
|
|
||||||
@ -506,11 +505,7 @@ func TestV3StorageQuotaAPI(t *testing.T) {
|
|||||||
|
|
||||||
// TestV3StorageQuotaApply tests the V3 server respects quotas during apply
|
// TestV3StorageQuotaApply tests the V3 server respects quotas during apply
|
||||||
func TestV3StorageQuotaApply(t *testing.T) {
|
func TestV3StorageQuotaApply(t *testing.T) {
|
||||||
oldSize := backend.InitialMmapSize
|
|
||||||
defer func() {
|
|
||||||
backend.InitialMmapSize = oldSize
|
|
||||||
testutil.AfterTest(t)
|
testutil.AfterTest(t)
|
||||||
}()
|
|
||||||
|
|
||||||
clus := NewClusterV3(t, &ClusterConfig{Size: 2})
|
clus := NewClusterV3(t, &ClusterConfig{Size: 2})
|
||||||
defer clus.Terminate(t)
|
defer clus.Terminate(t)
|
||||||
@ -518,7 +513,7 @@ func TestV3StorageQuotaApply(t *testing.T) {
|
|||||||
kvc1 := toGRPC(clus.Client(1)).KV
|
kvc1 := toGRPC(clus.Client(1)).KV
|
||||||
|
|
||||||
// force a node to have a different quota
|
// force a node to have a different quota
|
||||||
backend.InitialMmapSize = 64 * 1024
|
clus.Members[0].QuotaBackendBytes = 64 * 1024
|
||||||
clus.Members[0].Stop(t)
|
clus.Members[0].Stop(t)
|
||||||
clus.Members[0].Restart(t)
|
clus.Members[0].Restart(t)
|
||||||
clus.waitLeader(t, clus.Members)
|
clus.waitLeader(t, clus.Members)
|
||||||
@ -552,7 +547,6 @@ func TestV3StorageQuotaApply(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reset large quota node to ensure alarm persisted
|
// reset large quota node to ensure alarm persisted
|
||||||
backend.InitialMmapSize = oldSize
|
|
||||||
clus.Members[1].Stop(t)
|
clus.Members[1].Stop(t)
|
||||||
clus.Members[1].Restart(t)
|
clus.Members[1].Restart(t)
|
||||||
clus.waitLeader(t, clus.Members)
|
clus.waitLeader(t, clus.Members)
|
||||||
|
@ -41,6 +41,15 @@ var (
|
|||||||
InitialMmapSize = int64(10 * 1024 * 1024 * 1024)
|
InitialMmapSize = int64(10 * 1024 * 1024 * 1024)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultQuotaBytes is the number of bytes the backend Size may
|
||||||
|
// consume before exceeding the space quota.
|
||||||
|
DefaultQuotaBytes = int64(2 * 1024 * 1024 * 1024) // 2GB
|
||||||
|
// MaxQuotaBytes is the maximum number of bytes suggested for a backend
|
||||||
|
// quota. A larger quota may lead to degraded performance.
|
||||||
|
MaxQuotaBytes = int64(8 * 1024 * 1024 * 1024) // 8GB
|
||||||
|
)
|
||||||
|
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
BatchTx() BatchTx
|
BatchTx() BatchTx
|
||||||
Snapshot() Snapshot
|
Snapshot() Snapshot
|
||||||
|
Loading…
x
Reference in New Issue
Block a user