Skip to content

Commit

Permalink
Adding new parameter for more dynamic horizontal query sharding
Browse files Browse the repository at this point in the history
Signed-off-by: Pedro Tanaka <pedro.tanaka@shopify.com>
  • Loading branch information
pedro-stanaka committed Aug 30, 2022
1 parent 4d08130 commit e4a9894
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 11 deletions.
7 changes: 6 additions & 1 deletion cmd/thanos/query_frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,14 @@ func registerQueryFrontend(app *extkingpin.App) {
cmd.Flag("query-range.request-downsampled", "Make additional query for downsampled data in case of empty or incomplete response to range request.").
Default("true").BoolVar(&cfg.QueryRangeConfig.RequestDownsampled)

cmd.Flag("query-range.split-interval", "Split query range requests by an interval and execute in parallel, it should be greater than 0 when query-range.response-cache-config is configured.").
cmd.Flag("query-range.split-interval", "Split query range requests by an interval and execute in parallel, it should be greater than 0 when query-range.response-cache-config is configured."+
"When used in conjunction with query-range.min-split-interval this becomes the upper boundary interval to split queries into.").
Default("24h").DurationVar(&cfg.QueryRangeConfig.SplitQueriesByInterval)

cmd.Flag("query-range.min-split-interval", "Split query range requests by at least this interval."+
"It also should be less than query-range.split-interval.").
Default("0").DurationVar(&cfg.QueryRangeConfig.MinQuerySplitInterval)

cmd.Flag("query-range.max-retries-per-request", "Maximum number of retries for a single query range request; beyond this, the downstream error is returned.").
Default("5").IntVar(&cfg.QueryRangeConfig.MaxRetries)

Expand Down
1 change: 1 addition & 0 deletions pkg/queryfrontend/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ type QueryRangeConfig struct {
AlignRangeWithStep bool
RequestDownsampled bool
SplitQueriesByInterval time.Duration
MinQuerySplitInterval time.Duration
MaxRetries int
Limits *cortexvalidation.Limits
}
Expand Down
22 changes: 18 additions & 4 deletions pkg/queryfrontend/roundtrip.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,9 @@ func newQueryRangeTripperware(
)
}

queryIntervalFn := func(_ queryrange.Request) time.Duration {
return config.SplitQueriesByInterval
}

if config.SplitQueriesByInterval != 0 {
queryIntervalFn := dynamicIntervalFn(config)

queryRangeMiddleware = append(
queryRangeMiddleware,
queryrange.InstrumentMiddleware("split_by_interval", m),
Expand Down Expand Up @@ -237,6 +235,22 @@ func newQueryRangeTripperware(
}, nil
}

func dynamicIntervalFn(config QueryRangeConfig) queryrange.IntervalFn {
return func(r queryrange.Request) time.Duration {
if config.MinQuerySplitInterval == 0 && config.SplitQueriesByInterval != 0 {
return config.SplitQueriesByInterval
}

queryInterval := time.Duration(r.GetEnd()-r.GetStart()) * time.Millisecond
// if the query is multiple of max interval, we use the max interval.
if queryInterval/config.SplitQueriesByInterval >= 2 {
return config.SplitQueriesByInterval
}

return config.MinQuerySplitInterval
}
}

// newLabelsTripperware returns a Tripperware for labels and series requests
// configured with middlewares of split by interval and retry.
func newLabelsTripperware(
Expand Down
32 changes: 26 additions & 6 deletions pkg/queryfrontend/roundtrip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,13 @@ func TestRoundTripSplitIntervalMiddleware(t *testing.T) {
labelsCodec := NewThanosLabelsCodec(true, 2*time.Hour)

for _, tc := range []struct {
name string
splitInterval time.Duration
req queryrange.Request
codec queryrange.Codec
handlerFunc func(bool) (*int, http.Handler)
expected int
name string
splitInterval time.Duration
minSplitInterval time.Duration
req queryrange.Request
codec queryrange.Codec
handlerFunc func(bool) (*int, http.Handler)
expected int
}{
{
name: "split interval == 0, disable split",
Expand Down Expand Up @@ -280,6 +281,24 @@ func TestRoundTripSplitIntervalMiddleware(t *testing.T) {
splitInterval: 1 * time.Hour,
expected: 2,
},
{
name: "split to 4 requests, due to min interval",
req: testRequest,
handlerFunc: promqlResults,
codec: queryRangeCodec,
splitInterval: 2 * time.Hour,
minSplitInterval: 30 * time.Minute,
expected: 4,
},
{
name: "split to 2 requests, due to split interval",
req: testRequest,
handlerFunc: promqlResults,
codec: queryRangeCodec,
splitInterval: 1 * time.Hour,
minSplitInterval: 30 * time.Minute,
expected: 2,
},
{
name: "labels request won't be split",
req: testLabelsRequest,
Expand Down Expand Up @@ -320,6 +339,7 @@ func TestRoundTripSplitIntervalMiddleware(t *testing.T) {
QueryRangeConfig: QueryRangeConfig{
Limits: defaultLimits,
SplitQueriesByInterval: tc.splitInterval,
MinQuerySplitInterval: tc.minSplitInterval,
},
LabelsConfig: LabelsConfig{
Limits: defaultLimits,
Expand Down

0 comments on commit e4a9894

Please sign in to comment.