go-libp2p-resource-manager/limit.go

265 lines
6.3 KiB
Go
Raw Normal View History

2022-07-28 19:46:47 +08:00
/*
Package rcmgr is the resource manager for go-libp2p. This allows you to track
resources being used throughout your go-libp2p process. As well as making sure
that the process doesn't use more resources than what you define as your
limits. The resource manager only knows about things it is told about, so it's
the responsibility of the user of this library (either go-libp2p or a go-libp2p
user) to make sure they check with the resource manager before actually
allocating the resource.
*/
2021-12-22 17:39:46 +08:00
package rcmgr
2021-12-23 21:28:14 +08:00
import (
"encoding/json"
"io"
2021-12-23 21:28:14 +08:00
"github.com/libp2p/go-libp2p-core/network"
2021-12-23 23:46:08 +08:00
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/protocol"
2021-12-23 21:28:14 +08:00
)
2022-01-05 22:54:28 +08:00
// Limit is an object that specifies basic resource limits.
2021-12-22 17:39:46 +08:00
type Limit interface {
// GetMemoryLimit returns the (current) memory limit.
2021-12-22 17:39:46 +08:00
GetMemoryLimit() int64
// GetStreamLimit returns the stream limit, for inbound or outbound streams.
2021-12-23 21:28:14 +08:00
GetStreamLimit(network.Direction) int
2022-01-15 02:10:18 +08:00
// GetStreamTotalLimit returns the total stream limit
GetStreamTotalLimit() int
// GetConnLimit returns the connection limit, for inbound or outbound connections.
2021-12-23 21:28:14 +08:00
GetConnLimit(network.Direction) int
2022-01-15 02:10:18 +08:00
// GetConnTotalLimit returns the total connection limit
GetConnTotalLimit() int
// GetFDLimit returns the file descriptor limit.
2021-12-23 21:28:14 +08:00
GetFDLimit() int
2021-12-22 17:39:46 +08:00
}
2021-12-23 23:46:08 +08:00
2022-01-05 22:54:28 +08:00
// Limiter is the interface for providing limits to the resource manager.
2021-12-23 23:46:08 +08:00
type Limiter interface {
GetSystemLimits() Limit
GetTransientLimits() Limit
2022-07-02 04:39:13 +08:00
GetAllowlistedSystemLimits() Limit
GetAllowlistedTransientLimits() Limit
2021-12-23 23:46:08 +08:00
GetServiceLimits(svc string) Limit
GetServicePeerLimits(svc string) Limit
2021-12-23 23:46:08 +08:00
GetProtocolLimits(proto protocol.ID) Limit
GetProtocolPeerLimits(proto protocol.ID) Limit
2021-12-23 23:46:08 +08:00
GetPeerLimits(p peer.ID) Limit
GetStreamLimits(p peer.ID) Limit
GetConnLimits() Limit
}
2021-12-24 18:12:44 +08:00
// NewDefaultLimiterFromJSON creates a new limiter by parsing a json configuration,
// using the default limits for fallback.
func NewDefaultLimiterFromJSON(in io.Reader) (Limiter, error) {
return NewLimiterFromJSON(in, DefaultLimits.AutoScale())
}
// NewLimiterFromJSON creates a new limiter by parsing a json configuration.
func NewLimiterFromJSON(in io.Reader, defaults LimitConfig) (Limiter, error) {
cfg, err := readLimiterConfigFromJSON(in, defaults)
if err != nil {
return nil, err
}
return &fixedLimiter{cfg}, nil
}
func readLimiterConfigFromJSON(in io.Reader, defaults LimitConfig) (LimitConfig, error) {
var cfg LimitConfig
if err := json.NewDecoder(in).Decode(&cfg); err != nil {
return LimitConfig{}, err
}
2022-06-19 15:43:31 +08:00
cfg.Apply(defaults)
return cfg, nil
}
2022-06-10 22:01:03 +08:00
// fixedLimiter is a limiter with fixed limits.
type fixedLimiter struct {
LimitConfig
2021-12-24 18:12:44 +08:00
}
2022-06-10 22:01:03 +08:00
var _ Limiter = (*fixedLimiter)(nil)
func NewFixedLimiter(conf LimitConfig) Limiter {
log.Debugw("initializing new limiter with config", "limits", conf)
2022-06-10 22:01:03 +08:00
return &fixedLimiter{LimitConfig: conf}
}
2021-12-24 18:12:44 +08:00
2022-01-06 18:57:37 +08:00
// BaseLimit is a mixin type for basic resource limits.
type BaseLimit struct {
2022-01-15 02:10:18 +08:00
Streams int
2022-01-06 18:57:37 +08:00
StreamsInbound int
StreamsOutbound int
2022-01-15 02:10:18 +08:00
Conns int
2022-01-06 18:57:37 +08:00
ConnsInbound int
ConnsOutbound int
FD int
2022-06-10 22:01:03 +08:00
Memory int64
2022-01-05 22:54:28 +08:00
}
2022-06-19 15:43:31 +08:00
// Apply overwrites all zero-valued limits with the values of l2
// Must not use a pointer receiver.
func (l *BaseLimit) Apply(l2 BaseLimit) {
if l.Streams == 0 {
l.Streams = l2.Streams
}
if l.StreamsInbound == 0 {
l.StreamsInbound = l2.StreamsInbound
}
if l.StreamsOutbound == 0 {
l.StreamsOutbound = l2.StreamsOutbound
}
if l.Conns == 0 {
l.Conns = l2.Conns
}
if l.ConnsInbound == 0 {
l.ConnsInbound = l2.ConnsInbound
}
if l.ConnsOutbound == 0 {
l.ConnsOutbound = l2.ConnsOutbound
}
if l.Memory == 0 {
l.Memory = l2.Memory
}
if l.FD == 0 {
l.FD = l2.FD
}
}
2022-06-10 22:01:03 +08:00
// BaseLimitIncrease is the increase per GB of system memory.
type BaseLimitIncrease struct {
Streams int
StreamsInbound int
StreamsOutbound int
Conns int
ConnsInbound int
ConnsOutbound int
Memory int64
FDFraction float64
}
// Apply overwrites all zero-valued limits with the values of l2
2022-06-19 15:43:31 +08:00
// Must not use a pointer receiver.
func (l *BaseLimitIncrease) Apply(l2 BaseLimitIncrease) {
if l.Streams == 0 {
l.Streams = l2.Streams
}
if l.StreamsInbound == 0 {
l.StreamsInbound = l2.StreamsInbound
}
if l.StreamsOutbound == 0 {
l.StreamsOutbound = l2.StreamsOutbound
}
if l.Conns == 0 {
l.Conns = l2.Conns
}
if l.ConnsInbound == 0 {
l.ConnsInbound = l2.ConnsInbound
}
if l.ConnsOutbound == 0 {
l.ConnsOutbound = l2.ConnsOutbound
}
if l.Memory == 0 {
l.Memory = l2.Memory
}
2022-06-19 15:43:31 +08:00
if l.FDFraction == 0 {
l.FDFraction = l2.FDFraction
}
}
2022-01-05 22:54:28 +08:00
func (l *BaseLimit) GetStreamLimit(dir network.Direction) int {
2021-12-24 18:12:44 +08:00
if dir == network.DirInbound {
return l.StreamsInbound
} else {
return l.StreamsOutbound
}
}
2022-01-15 02:10:18 +08:00
func (l *BaseLimit) GetStreamTotalLimit() int {
return l.Streams
}
2022-01-05 22:54:28 +08:00
func (l *BaseLimit) GetConnLimit(dir network.Direction) int {
2021-12-24 18:12:44 +08:00
if dir == network.DirInbound {
return l.ConnsInbound
} else {
return l.ConnsOutbound
}
}
2022-01-15 02:10:18 +08:00
func (l *BaseLimit) GetConnTotalLimit() int {
return l.Conns
}
2022-01-05 22:54:28 +08:00
func (l *BaseLimit) GetFDLimit() int {
2021-12-24 18:12:44 +08:00
return l.FD
}
2022-06-10 22:01:03 +08:00
func (l *BaseLimit) GetMemoryLimit() int64 {
return l.Memory
}
func (l *fixedLimiter) GetSystemLimits() Limit {
return &l.System
2021-12-24 18:12:44 +08:00
}
2022-06-10 22:01:03 +08:00
func (l *fixedLimiter) GetTransientLimits() Limit {
return &l.Transient
2021-12-24 18:12:44 +08:00
}
2022-07-02 04:39:13 +08:00
func (l *fixedLimiter) GetAllowlistedSystemLimits() Limit {
return &l.AllowlistedSystem
}
func (l *fixedLimiter) GetAllowlistedTransientLimits() Limit {
return &l.AllowlistedTransient
}
2022-06-10 22:01:03 +08:00
func (l *fixedLimiter) GetServiceLimits(svc string) Limit {
sl, ok := l.Service[svc]
2021-12-24 18:12:44 +08:00
if !ok {
return &l.ServiceDefault
2021-12-24 18:12:44 +08:00
}
2022-06-10 22:01:03 +08:00
return &sl
2021-12-24 18:12:44 +08:00
}
2022-06-10 22:01:03 +08:00
func (l *fixedLimiter) GetServicePeerLimits(svc string) Limit {
pl, ok := l.ServicePeer[svc]
if !ok {
return &l.ServicePeerDefault
}
2022-06-10 22:01:03 +08:00
return &pl
}
2022-06-10 22:01:03 +08:00
func (l *fixedLimiter) GetProtocolLimits(proto protocol.ID) Limit {
pl, ok := l.Protocol[proto]
2021-12-24 18:12:44 +08:00
if !ok {
return &l.ProtocolDefault
2021-12-24 18:12:44 +08:00
}
2022-06-10 22:01:03 +08:00
return &pl
2021-12-24 18:12:44 +08:00
}
2022-06-10 22:01:03 +08:00
func (l *fixedLimiter) GetProtocolPeerLimits(proto protocol.ID) Limit {
pl, ok := l.ProtocolPeer[proto]
if !ok {
return &l.ProtocolPeerDefault
}
2022-06-10 22:01:03 +08:00
return &pl
}
2022-06-10 22:01:03 +08:00
func (l *fixedLimiter) GetPeerLimits(p peer.ID) Limit {
pl, ok := l.Peer[p]
2021-12-24 18:12:44 +08:00
if !ok {
return &l.PeerDefault
2021-12-24 18:12:44 +08:00
}
2022-06-10 22:01:03 +08:00
return &pl
2021-12-24 18:12:44 +08:00
}
2022-01-06 18:57:37 +08:00
2022-06-10 22:01:03 +08:00
func (l *fixedLimiter) GetStreamLimits(_ peer.ID) Limit {
return &l.Stream
2022-01-06 18:57:37 +08:00
}
2022-01-13 21:37:02 +08:00
2022-06-10 22:01:03 +08:00
func (l *fixedLimiter) GetConnLimits() Limit {
return &l.Conn
2022-01-13 21:37:02 +08:00
}