From 0d45c38782b0c14f1820bb4d1fa0e8b145dd3926 Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Wed, 30 Sep 2020 21:38:27 +0100 Subject: [PATCH] List v1/versions routes based on source IP if found (#10603) Routing using on source IP if found. This should distribute the listing load for V1 and versioning on multiple nodes evenly between different clients. If source IP is not found from the http request header, then falls back to bucket name instead. --- cmd/bucket-listobjects-handlers.go | 19 +++++++++++++++---- pkg/handlers/proxy.go | 14 ++++++++++---- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/cmd/bucket-listobjects-handlers.go b/cmd/bucket-listobjects-handlers.go index 9e9a55aff..30c09c899 100644 --- a/cmd/bucket-listobjects-handlers.go +++ b/cmd/bucket-listobjects-handlers.go @@ -27,6 +27,7 @@ import ( "github.com/minio/minio/cmd/logger" "github.com/minio/minio/pkg/bucket/policy" + "github.com/minio/minio/pkg/handlers" "github.com/minio/minio/pkg/sync/errgroup" ) @@ -113,7 +114,12 @@ func (api objectAPIHandlers) ListObjectVersionsHandler(w http.ResponseWriter, r return } - if proxyRequestByBucket(ctx, w, r, bucket) { + // Forward the request using Source IP or bucket + forwardStr := handlers.GetSourceIPFromHeaders(r) + if forwardStr == "" { + forwardStr = bucket + } + if proxyRequestByStringHash(ctx, w, r, forwardStr) { return } @@ -340,8 +346,8 @@ func proxyRequestByNodeIndex(ctx context.Context, w http.ResponseWriter, r *http return proxyRequest(ctx, w, r, ep) } -func proxyRequestByBucket(ctx context.Context, w http.ResponseWriter, r *http.Request, bucket string) (success bool) { - return proxyRequestByNodeIndex(ctx, w, r, crcHashMod(bucket, len(globalProxyEndpoints))) +func proxyRequestByStringHash(ctx context.Context, w http.ResponseWriter, r *http.Request, str string) (success bool) { + return proxyRequestByNodeIndex(ctx, w, r, crcHashMod(str, len(globalProxyEndpoints))) } // ListObjectsV1Handler - GET Bucket (List Objects) Version 1. @@ -382,7 +388,12 @@ func (api objectAPIHandlers) ListObjectsV1Handler(w http.ResponseWriter, r *http return } - if proxyRequestByBucket(ctx, w, r, bucket) { + // Forward the request using Source IP or bucket + forwardStr := handlers.GetSourceIPFromHeaders(r) + if forwardStr == "" { + forwardStr = bucket + } + if proxyRequestByStringHash(ctx, w, r, forwardStr) { return } diff --git a/pkg/handlers/proxy.go b/pkg/handlers/proxy.go index 761cf0b89..e0efdae24 100644 --- a/pkg/handlers/proxy.go +++ b/pkg/handlers/proxy.go @@ -74,10 +74,9 @@ func GetSourceScheme(r *http.Request) string { return scheme } -// GetSourceIP retrieves the IP from the X-Forwarded-For, X-Real-IP and RFC7239 -// Forwarded headers (in that order), falls back to r.RemoteAddr when all -// else fails. -func GetSourceIP(r *http.Request) string { +// GetSourceIPFromHeaders retrieves the IP from the X-Forwarded-For, X-Real-IP +// and RFC7239 Forwarded headers (in that order) +func GetSourceIPFromHeaders(r *http.Request) string { var addr string if fwd := r.Header.Get(xForwardedFor); fwd != "" { @@ -106,6 +105,13 @@ func GetSourceIP(r *http.Request) string { } } + return addr +} + +// GetSourceIP retrieves the IP from the request headers +// and falls back to r.RemoteAddr when necessary. +func GetSourceIP(r *http.Request) string { + addr := GetSourceIPFromHeaders(r) if addr != "" { return addr }