forked from TrueCloudLab/frostfs-node
[#676] services/container: Cache the results of read operations
In previous implementation Container service handlers didn't cache the results of `Get` / `GetEACL` / `List` operations. As a consequence of this, high load on the service caused neo-go client's connection errors. To avoid this there is a need to use cache. Object service already uses `Get` and `GetEACL` caches. Implement cache of `List` results. Share already implemented cache of Object service with the Container one. Provide new instance of read-only container storage (defined as an interface)to morph executor's constructor on which container service is based. Write operations remained unchanged. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
c54f524df9
commit
e738699fcc
5 changed files with 115 additions and 30 deletions
|
@ -8,10 +8,12 @@ import (
|
|||
"fmt"
|
||||
"strconv"
|
||||
|
||||
eaclSDK "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
|
||||
apiClient "github.com/nspcc-dev/neofs-api-go/pkg/client"
|
||||
containerSDK "github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/netmap"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||
containerV2 "github.com/nspcc-dev/neofs-api-go/v2/container"
|
||||
containerGRPC "github.com/nspcc-dev/neofs-api-go/v2/container/grpc"
|
||||
containerCore "github.com/nspcc-dev/neofs-node/pkg/core/container"
|
||||
|
@ -28,6 +30,7 @@ import (
|
|||
placementrouter "github.com/nspcc-dev/neofs-node/pkg/services/container/announcement/load/route/placement"
|
||||
loadstorage "github.com/nspcc-dev/neofs-node/pkg/services/container/announcement/load/storage"
|
||||
containerMorph "github.com/nspcc-dev/neofs-node/pkg/services/container/morph"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/util/logger"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
@ -43,16 +46,26 @@ func initContainerService(c *cfg) {
|
|||
|
||||
cnrSrc := wrapper.AsContainerSource(wrap)
|
||||
|
||||
var containerSource containerCore.Source
|
||||
|
||||
if c.cfgMorph.disableCache {
|
||||
containerSource = cnrSrc
|
||||
} else {
|
||||
containerSource = newCachedContainerStorage(cnrSrc) // use RPC node as source of containers (with caching)
|
||||
eACLFetcher := &morphEACLFetcher{
|
||||
w: wrap,
|
||||
}
|
||||
|
||||
c.cfgObject.cnrSource = containerSource
|
||||
c.cfgObject.cnrClient = wrap
|
||||
cnrRdr := new(morphContainerReader)
|
||||
|
||||
if c.cfgMorph.disableCache {
|
||||
c.cfgObject.eaclSource = eACLFetcher
|
||||
cnrRdr.eacl = eACLFetcher
|
||||
c.cfgObject.cnrSource = cnrSrc
|
||||
cnrRdr.get = cnrSrc
|
||||
cnrRdr.lister = wrap
|
||||
} else {
|
||||
// use RPC node as source of Container contract items (with caching)
|
||||
c.cfgObject.eaclSource = newCachedEACLStorage(eACLFetcher)
|
||||
c.cfgObject.cnrSource = newCachedContainerStorage(cnrSrc)
|
||||
cnrRdr.lister = newCachedContainerLister(wrap)
|
||||
cnrRdr.eacl = c.cfgObject.eaclSource
|
||||
cnrRdr.get = c.cfgObject.cnrSource
|
||||
}
|
||||
|
||||
localMetrics := &localStorageLoad{
|
||||
log: c.log,
|
||||
|
@ -122,7 +135,7 @@ func initContainerService(c *cfg) {
|
|||
&c.key.PrivateKey,
|
||||
containerService.NewResponseService(
|
||||
&usedSpaceService{
|
||||
Server: containerService.NewExecutionService(containerMorph.NewExecutor(wrap)),
|
||||
Server: containerService.NewExecutionService(containerMorph.NewExecutor(wrap, cnrRdr)),
|
||||
loadWriterProvider: loadRouter,
|
||||
loadPlacementBuilder: loadPlacementBuilder,
|
||||
routeBuilder: routeBuilder,
|
||||
|
@ -481,3 +494,26 @@ func (c *usedSpaceService) processLoadValue(ctx context.Context, a containerSDK.
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// implements interface required by container service provided by morph executor.
|
||||
type morphContainerReader struct {
|
||||
eacl eacl.Source
|
||||
|
||||
get containerCore.Source
|
||||
|
||||
lister interface {
|
||||
List(*owner.ID) ([]*cid.ID, error)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *morphContainerReader) Get(id *cid.ID) (*containerSDK.Container, error) {
|
||||
return x.get.Get(id)
|
||||
}
|
||||
|
||||
func (x *morphContainerReader) GetEACL(id *cid.ID) (*eaclSDK.Table, error) {
|
||||
return x.eacl.GetEACL(id)
|
||||
}
|
||||
|
||||
func (x *morphContainerReader) List(id *owner.ID) ([]*cid.ID, error) {
|
||||
return x.lister.List(id)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue