Browse Source

improve: add data center preference and URL shuffling for consistent performance

Added missing data center preference and load distribution (URL shuffling)
to ensure consistent performance and behavior across all code paths.

Problem 1: PreferPublicUrl path missing DC preference and shuffling
Location: weed/wdclient/filer_client.go lines 184-192

The custom PreferPublicUrl implementation was simply iterating through
locations and building URLs without considering:
  1. Data center proximity (latency optimization)
  2. Load distribution across volume servers

Before:
  for _, loc := range locations {
    url := loc.PublicUrl
    if url == "" { url = loc.Url }
    fullUrls = append(fullUrls, "http://"+url+"/"+fileId)
  }
  return fullUrls, nil

After:
  var sameDcUrls, otherDcUrls []string
  dataCenter := fc.GetDataCenter()
  for _, loc := range locations {
    url := loc.PublicUrl
    if url == "" { url = loc.Url }
    httpUrl := "http://" + url + "/" + fileId
    if dataCenter != "" && dataCenter == loc.DataCenter {
      sameDcUrls = append(sameDcUrls, httpUrl)
    } else {
      otherDcUrls = append(otherDcUrls, httpUrl)
    }
  }
  rand.Shuffle(len(sameDcUrls), ...)
  rand.Shuffle(len(otherDcUrls), ...)
  fullUrls = append(sameDcUrls, otherDcUrls...)

Problem 2: Cache miss path missing URL shuffling
Location: weed/wdclient/vidmap_client.go lines 95-108

The cache miss path (fallback lookup) was missing URL shuffling, while
the cache hit path (vm.LookupFileId) already shuffles URLs. This
inconsistency meant:
  - Cache hit: URLs shuffled → load distributed
  - Cache miss: URLs not shuffled → first server always hit

Before:
  var sameDcUrls, otherDcUrls []string
  // ... build URLs ...
  fullUrls = append(sameDcUrls, otherDcUrls...)
  return fullUrls, nil

After:
  var sameDcUrls, otherDcUrls []string
  // ... build URLs ...
  rand.Shuffle(len(sameDcUrls), ...)
  rand.Shuffle(len(otherDcUrls), ...)
  fullUrls = append(sameDcUrls, otherDcUrls...)
  return fullUrls, nil

Benefits:
  ✓ Reduced latency by preferring same-DC volume servers
  ✓ Even load distribution across all volume servers
  ✓ Consistent behavior between cache hit/miss paths
  ✓ Consistent behavior between PreferUrl and PreferPublicUrl
  ✓ Matches behavior of existing vidMap.LookupFileId implementation

Impact on performance:
  - Lower read latency (same-DC preference)
  - Better volume server utilization (load spreading)
  - No single volume server becomes a hotspot

Note: Added math/rand import to vidmap_client.go for shuffle support.
pull/7518/head
chrislu 2 weeks ago
parent
commit
8eb1c733d0
  1. 16
      weed/wdclient/filer_client.go
  2. 5
      weed/wdclient/vidmap_client.go

16
weed/wdclient/filer_client.go

@ -181,14 +181,26 @@ func (fc *FilerClient) GetLookupFileIdFunction() LookupFileIdFunctionType {
// Volume found successfully - ignore any errors about other volumes // Volume found successfully - ignore any errors about other volumes
// (not relevant for single-volume lookup, but defensive for future batching) // (not relevant for single-volume lookup, but defensive for future batching)
// Build URLs with publicUrl preference
// Build URLs with publicUrl preference, and also prefer same DC
var sameDcUrls, otherDcUrls []string
dataCenter := fc.GetDataCenter()
for _, loc := range locations { for _, loc := range locations {
url := loc.PublicUrl url := loc.PublicUrl
if url == "" { if url == "" {
url = loc.Url url = loc.Url
} }
fullUrls = append(fullUrls, "http://"+url+"/"+fileId)
httpUrl := "http://" + url + "/" + fileId
if dataCenter != "" && dataCenter == loc.DataCenter {
sameDcUrls = append(sameDcUrls, httpUrl)
} else {
otherDcUrls = append(otherDcUrls, httpUrl)
}
} }
// Shuffle to distribute load across volume servers
rand.Shuffle(len(sameDcUrls), func(i, j int) { sameDcUrls[i], sameDcUrls[j] = sameDcUrls[j], sameDcUrls[i] })
rand.Shuffle(len(otherDcUrls), func(i, j int) { otherDcUrls[i], otherDcUrls[j] = otherDcUrls[j], otherDcUrls[i] })
// Prefer same data center
fullUrls = append(sameDcUrls, otherDcUrls...)
return fullUrls, nil return fullUrls, nil
} }
} }

5
weed/wdclient/vidmap_client.go

@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"math/rand"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
@ -103,6 +104,10 @@ func (vc *vidMapClient) LookupFileIdWithFallback(ctx context.Context, fileId str
} }
} }
// Shuffle to distribute load across volume servers
rand.Shuffle(len(sameDcUrls), func(i, j int) { sameDcUrls[i], sameDcUrls[j] = sameDcUrls[j], sameDcUrls[i] })
rand.Shuffle(len(otherDcUrls), func(i, j int) { otherDcUrls[i], otherDcUrls[j] = otherDcUrls[j], otherDcUrls[i] })
// Prefer same data center // Prefer same data center
fullUrls = append(sameDcUrls, otherDcUrls...) fullUrls = append(sameDcUrls, otherDcUrls...)
return fullUrls, nil return fullUrls, nil

Loading…
Cancel
Save