Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

modify current limit parameters dynamically (volume dimension) #3026

Closed
wants to merge 3 commits into from

Conversation

ZLEternity
Copy link

Modify juicefs client upload/download limit parameters dynamically.

Add parameters(flags) in format settings, and modify the value through the 'juicefs config' to dynamically modify the traffiic(object storage) limiting bucket setting, which acts on the volume level.

The priority of new configuration is lower than the mount parameter.

The commit use official rate package(golang) , And allow control of timeout, but it seems that there is no high necessity., in order to make the use easier, all case set to no timeout.

Test Result:

  1. Unlimited upload/download
    default 0 in format setting

./juicefs bench /tmp/zmc-1112 -p 4
image

  1. Update upload/download limit(480 Mbps = 60MB, 960 Mbps = 120 MB)
    ./juicefs config tikv://xxx:2379/zmc-1112 --default-upload-limit 480 --default-download-limit 960

image

  1. Update upload/download limit
    ./juicefs config tikv://1xxx:2379/zmc-1112 --default-upload-limit 480 --default-download-limit 480

image

  1. Close upload/download limit
    ./juicefs config tikv://xxx:2379/zmc-1112 --default-upload-limit 0 --default-download-limit 0

image

@@ -42,6 +42,8 @@ const SlowRequest = time.Second * time.Duration(10)

var (
logger = utils.GetLogger("juicefs")
UseMountUploadLimitConf = false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to add a Reload() interface for chunk.Config and hide these details inside chunk/

Because we may want to reload other fields of chunk.Config, and we don't add these for them.

@ZLEternity
Copy link
Author

hide set conf logic inside chunk module.
But UseMountUploadLimitConf/UseMountDownloadLimitConf is only set once during mount, and will not be updated. It seems that reload/callback is not need.

err = s.store.downLimit.WaitN(context.TODO(), len(p))
if err != nil {
s.store.getTokenFromBucketErrors.WithLabelValues("download").Add(1)
return 0, fmt.Errorf("method: ReadAt, key = %s, get token from tokenBucket, need token count (page) = %d, error : %s", key, len(p), err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not fail the read() if waitN fail

var err = store.upLimit.WaitN(context.TODO(), len(p.Data))
if err != nil {
store.getTokenFromBucketErrors.WithLabelValues("upload").Add(1)
return fmt.Errorf("method: put, key = %s, get token from tokenBucket, need token count (page.Data) = %d, error : %s", key, len(p.Data), err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

objectReqsHistogram *prometheus.HistogramVec
objectReqErrors prometheus.Counter
objectDataBytes *prometheus.CounterVec
getTokenFromBucketErrors *prometheus.CounterVec
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's better to have metric for the wait period, other than errors

@@ -613,7 +634,11 @@ func (store *cachedStore) load(key string, page *Page, cache bool, forceCache bo
compressed := needed > len(page.Data)
// we don't know the actual size for compressed block
if store.downLimit != nil && !compressed {
store.downLimit.Wait(int64(len(page.Data)))
err = store.downLimit.WaitN(context.TODO(), len(page.Data))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we change to use golang.org/x/time/rate? When it will return error?

logger.Error("get %s: %s", key, err)
}
var err1 error
if store.downLimit != nil && compressed {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a race between UpdateCachedStoreRateLimit and here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. fixbug rate
  2. golang.org/x/time/rate allows update limit or burst, can ensure concurrency.
  3. It returns an error if n exceeds the Limiter's burst size, the Context is canceled, or the expected wait time exceeds the Context's Deadline.
    cancel and timeout are not set here, so only n(token count) is larger than burst size, can cause error. To ensure the effect of rate.limiter, this case should not be executed normally.
  4. about metrics, make tokens at a constant speed(rate.NewLimiter), we may prefer to know whether there are config exception. if it is normal, block until get the needed tokens.

@davies
Copy link
Contributor

davies commented May 10, 2023

This PR is took over by #3574 , thanks!

@davies davies closed this May 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants