satellite/overlay: add feature flag for node selection cache

Also distinguish the purpose for selecting nodes to avoid potential
confusion, what should allow caching and what shouldn't.

Change-Id: Iee2451c1f10d0f1c81feb1641507400d89918d61
This commit is contained in:
Egon Elbre 2020-05-06 16:05:31 +03:00
parent e4da7d65f0
commit 4e94da3fda
8 changed files with 40 additions and 20 deletions

View File

@ -174,7 +174,7 @@ func TestDisqualifiedNodesGetNoUpload(t *testing.T) {
ExcludedIDs: nil,
MinimumVersion: "", // semver or empty
}
nodes, err := satellitePeer.Overlay.Service.FindStorageNodes(ctx, request)
nodes, err := satellitePeer.Overlay.Service.FindStorageNodesForUpload(ctx, request)
assert.True(t, overlay.ErrNotEnoughNodes.Has(err))
assert.Len(t, nodes, 3)

View File

@ -399,7 +399,7 @@ func (endpoint *Endpoint) processIncomplete(ctx context.Context, stream processS
ExcludedIDs: excludedIDs,
}
newNodes, err := endpoint.overlay.FindStorageNodes(ctx, *request)
newNodes, err := endpoint.overlay.FindStorageNodesForGracefulExit(ctx, *request)
if err != nil {
return Error.Wrap(err)
}

View File

@ -207,7 +207,7 @@ func (endpoint *Endpoint) CreateSegmentOld(ctx context.Context, req *pb.SegmentW
request := overlay.FindStorageNodesRequest{
RequestedCount: int(req.Redundancy.Total),
}
nodes, err := endpoint.overlay.FindStorageNodes(ctx, request)
nodes, err := endpoint.overlay.FindStorageNodesForUpload(ctx, request)
if err != nil {
return nil, rpcstatus.Error(rpcstatus.Internal, err.Error())
}
@ -1420,7 +1420,7 @@ func (endpoint *Endpoint) BeginSegment(ctx context.Context, req *pb.SegmentBegin
request := overlay.FindStorageNodesRequest{
RequestedCount: redundancy.TotalCount(),
}
nodes, err := endpoint.overlay.FindStorageNodes(ctx, request)
nodes, err := endpoint.overlay.FindStorageNodesForUpload(ctx, request)
if err != nil {
return nil, rpcstatus.Error(rpcstatus.Internal, err.Error())
}

View File

@ -410,7 +410,7 @@ func BenchmarkNodeSelection(b *testing.B) {
b.Run("FindStorageNodes", func(b *testing.B) {
for i := 0; i < b.N; i++ {
selected, err := service.FindStorageNodes(ctx, overlay.FindStorageNodesRequest{
selected, err := service.FindStorageNodesForUpload(ctx, overlay.FindStorageNodesRequest{
MinimumRequiredNodes: SelectCount,
RequestedCount: SelectCount,
ExcludedIDs: nil,
@ -423,7 +423,7 @@ func BenchmarkNodeSelection(b *testing.B) {
b.Run("FindStorageNodesExclusion", func(b *testing.B) {
for i := 0; i < b.N; i++ {
selected, err := service.FindStorageNodes(ctx, overlay.FindStorageNodesRequest{
selected, err := service.FindStorageNodesForUpload(ctx, overlay.FindStorageNodesRequest{
MinimumRequiredNodes: SelectCount,
RequestedCount: SelectCount,
ExcludedIDs: excludedIDs,

View File

@ -22,6 +22,7 @@ type CacheDB interface {
// CacheConfig is a configuration for overlay node selection cache.
type CacheConfig struct {
Disabled bool `help:"disable node cache" releaseDefault:"true" devDefault:"false"`
Staleness time.Duration `help:"how stale the node selection cache can be" releaseDefault:"3m" devDefault:"5m"`
}

View File

@ -76,7 +76,7 @@ func TestMinimumDiskSpace(t *testing.T) {
}
// request 2 nodes, expect failure from not enough nodes
n1, err := saOverlay.Service.FindStorageNodes(ctx, req)
n1, err := saOverlay.Service.FindStorageNodesForUpload(ctx, req)
require.Error(t, err)
require.True(t, overlay.ErrNotEnoughNodes.Has(err))
n2, err := saOverlay.Service.SelectionCache.GetNodes(ctx, req)
@ -99,7 +99,7 @@ func TestMinimumDiskSpace(t *testing.T) {
require.NoError(t, err)
// request 2 nodes, expect success
n1, err = planet.Satellites[0].Overlay.Service.FindStorageNodes(ctx, req)
n1, err = planet.Satellites[0].Overlay.Service.FindStorageNodesForUpload(ctx, req)
require.NoError(t, err)
require.Equal(t, 2, len(n1))
n2, err = saOverlay.Service.FindStorageNodesWithPreferences(ctx, req, &nodeConfig)
@ -545,7 +545,7 @@ func TestFindStorageNodesDistinctNetworks(t *testing.T) {
RequestedCount: 2,
ExcludedIDs: excludedNodes,
}
nodes, err := satellite.Overlay.Service.FindStorageNodes(ctx, req)
nodes, err := satellite.Overlay.Service.FindStorageNodesForUpload(ctx, req)
require.NoError(t, err)
require.Len(t, nodes, 2)
require.NotEqual(t, nodes[0].LastIPPort, nodes[1].LastIPPort)
@ -569,7 +569,7 @@ func TestFindStorageNodesDistinctNetworks(t *testing.T) {
RequestedCount: 4,
ExcludedIDs: excludedNodes,
}
n, err := satellite.Overlay.Service.FindStorageNodes(ctx, req)
n, err := satellite.Overlay.Service.FindStorageNodesForUpload(ctx, req)
require.Error(t, err)
n1, err := satellite.Overlay.Service.FindStorageNodesWithPreferences(ctx, req, &satellite.Config.Overlay.Node)
require.Error(t, err)
@ -624,7 +624,7 @@ func TestSelectNewStorageNodesExcludedIPs(t *testing.T) {
RequestedCount: 2,
ExcludedIDs: excludedNodes,
}
nodes, err := satellite.Overlay.Service.FindStorageNodes(ctx, req)
nodes, err := satellite.Overlay.Service.FindStorageNodesForUpload(ctx, req)
require.NoError(t, err)
require.Len(t, nodes, 2)
require.NotEqual(t, nodes[0].LastIPPort, nodes[1].LastIPPort)
@ -783,7 +783,7 @@ func TestCacheSelectionVsDBSelection(t *testing.T) {
nodeConfig := planet.Satellites[0].Config.Overlay.Node
req := overlay.FindStorageNodesRequest{RequestedCount: 5}
n1, err := saOverlay.Service.FindStorageNodes(ctx, req)
n1, err := saOverlay.Service.FindStorageNodesForUpload(ctx, req)
require.NoError(t, err)
n2, err := saOverlay.Service.SelectionCache.GetNodes(ctx, req)
require.NoError(t, err)

View File

@ -279,19 +279,33 @@ func (service *Service) IsOnline(node *NodeDossier) bool {
return time.Since(node.Reputation.LastContactSuccess) < service.config.Node.OnlineWindow
}
// FindStorageNodesForRepair searches the overlay network for nodes that meet the provided requirements for repair
// The main difference between this method and the normal FindStorageNodes is that here we filter out all nodes that
// share a subnet with any node in req.ExcludedIDs. This additional complexity is not needed for other uses of finding storage nodes
// FindStorageNodesForRepair searches the overlay network for nodes that meet the provided requirements for repair.
//
// The main difference from FindStorageNodesForUpload is that here we filter out all nodes that share a subnet with any node in req.ExcludedIDs.
// This additional complexity is not needed for other uses of finding storage nodes.
func (service *Service) FindStorageNodesForRepair(ctx context.Context, req FindStorageNodesRequest) (_ []*SelectedNode, err error) {
defer mon.Task()(&ctx)(&err)
return service.FindStorageNodesWithPreferences(ctx, req, &service.config.Node)
}
// FindStorageNodes searches the overlay network for nodes that meet the provided requirements,
// it first searches the selected nodes cache, if there aren't enough nodes in the
// cache (which shouldn't typically happen), then it resorts back to selecting nodes from the the nodes table
func (service *Service) FindStorageNodes(ctx context.Context, req FindStorageNodesRequest) (_ []*SelectedNode, err error) {
// FindStorageNodesForGracefulExit searches the overlay network for nodes that meet the provided requirements for graceful-exit requests.
//
// The main difference between this method and the normal FindStorageNodes is that here we avoid using the cache.
func (service *Service) FindStorageNodesForGracefulExit(ctx context.Context, req FindStorageNodesRequest) (_ []*SelectedNode, err error) {
defer mon.Task()(&ctx)(&err)
return service.FindStorageNodesWithPreferences(ctx, req, &service.config.Node)
}
// FindStorageNodesForUpload searches the overlay network for nodes that meet the provided requirements for upload.
//
// When enabled it uses the cache to select nodes.
// When the node selection from the cache fails, it falls back to the old implementation.
func (service *Service) FindStorageNodesForUpload(ctx context.Context, req FindStorageNodesRequest) (_ []*SelectedNode, err error) {
defer mon.Task()(&ctx)(&err)
if service.config.NodeSelectionCache.Disabled {
return service.FindStorageNodesWithPreferences(ctx, req, &service.config.Node)
}
selectedNodes, err := service.SelectionCache.GetNodes(ctx, req)
if err != nil {
service.log.Warn("error selecting from node selection cache", zap.String("err", err.Error()))
@ -303,7 +317,9 @@ func (service *Service) FindStorageNodes(ctx context.Context, req FindStorageNod
return selectedNodes, nil
}
// FindStorageNodesWithPreferences searches the overlay network for nodes that meet the provided criteria
// FindStorageNodesWithPreferences searches the overlay network for nodes that meet the provided criteria.
//
// This does not use a cache.
func (service *Service) FindStorageNodesWithPreferences(ctx context.Context, req FindStorageNodesRequest, preferences *NodeSelectionConfig) (nodes []*SelectedNode, err error) {
defer mon.Task()(&ctx)(&err)

View File

@ -418,6 +418,9 @@ identity.key-path: /root/.local/share/storj/identity/satellite/identity.key
# how many orders to batch per transaction
# orders.settlement-batch-size: 250
# disable node cache
# overlay.node-selection-cache.disabled: true
# how stale the node selection cache can be
# overlay.node-selection-cache.staleness: 3m0s