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

Enabled mc quota to set bucket throttle config #4780

Closed
wants to merge 5 commits into from

Conversation

shtripat
Copy link
Contributor

@shtripat shtripat commented Dec 4, 2023

Community Contribution License

All community contributions in this pull request are licensed to the project maintainers
under the terms of the [Apache 2 license] (https://www.apache.org/licenses/LICENSE-2.0).
By creating this pull request I represent that I have the right to license the
contributions to the project maintainers under the Apache 2 license.

Description

Motivation and Context

How to test this PR?

  1. mc quota set m1/test-bucket --concurrent-requests-count 200 --apis "PutObject,DeleteObject,Get*" --size 2GB
  2. mc quota set m1/test-bucket --throttle-rules-file ./trules.json
    Sample trules.json
[
  {
    "concurrentRequestsCount": 100,
    "apis": [
      "PutObject",
      "ListObjects"
    ]
  },
  {
    "concurrentRequestsCount": 100,
    "apis": [
      "Get*"
    ]
  }
]
  1. mc quota info m1/test-bucket
Bucket `test-bucket` has hard quota of 1.9 GiB
Throttle configuration:
- ID: clsp0hdb4dtl5hl26380, Concurrent Requests Count: 200, APIs: DeleteObject,Get*,PutObject
  1. mc quota info m1/test-bucket --json
{
 "status": "success",
 "bucket": "test-bucket",
 "quota": 2000000000,
 "type": "hard",
 "throttleRules": [
  {
   "ID": "clsp0hdb4dtl5hl26380",
   "concurrentRequestsCount": 200,
   "apis": [
    "DeleteObject",
    "Get*",
    "PutObject"
   ]
  }
 ]
}
  1. Test throttle quota in effect
    Set really small values for --concurrent-requests-count for few APIs (say PutObject and HeadObject) as below
    mc quota set m1/test-bucket --concurrent-requests-count 10 --apis "PutObject,Get*,Head*,List*"
    Run mc admin trace m1 -v from another terminal session for detailed view of S3 calls and request/response.
    Now use below sample go code to simulate parallel requests to bucket and you should be seeing few Throttle quota exceeded. Applied RuleID: clsp1btb4dtl7p6ad190, Allowed Requests Count: 10, Current Requets Count: 59, API: PutObject errors.
    For this there are sample 1MB files (count 500) under ./data dir
package main

import (
        "context"
        "fmt"
        "os"
        "sync"

        minio "github.com/minio/minio-go/v7"
        "github.com/minio/minio-go/v7/pkg/credentials"
)

func main() {
        var wg sync.WaitGroup
        wg.Add(500)

        for i:=0; i<500; i++ {
                objName := fmt.Sprintf("file%d", i+1)
                fileName := fmt.Sprintf("./data/file%d", i+1)
                go func(obj, file string) {
                        defer wg.Done()
                        endpoint := "localhost:9000"
                        accessKeyID := "minioadmin"
                        secretAccessKey := "minioadmin"
                        useSSL := false

                        // Initialize minio client object.
                        minioClient, err := minio.New(endpoint, &minio.Options{
                                Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
                                Secure: useSSL,
                        })
                        if err != nil {
                                fmt.Println(err)
                                return
                        }
                        ctx := context.Background()

                        f, err := os.Open(file)
                        if err != nil {
                                fmt.Println(err)
                                return
                        }
                        defer f.Close()
                        fStat, err := f.Stat()
                        if err != nil {
                                fmt.Println(err)
                                return
                        }
                        
                        info, err := minioClient.PutObject(ctx, "test-bucket", obj, f, fStat.Size(),
                                            minio.PutObjectOptions{ContentType:"application/octet-stream"})
                        if err != nil {
                              fmt.Println(err)
                              return
                        }
                        fmt.Println("Loaded: ", info)
                }(objName, fileName)
        }
        wg.Wait()
}
package main

import (
        "context"
        "fmt"
        "io"
        "os"
        "sync"

        minio "github.com/minio/minio-go/v7"
        "github.com/minio/minio-go/v7/pkg/credentials"
)

func main() {
        var wg sync.WaitGroup
        wg.Add(500)

        for i:=0; i<500; i++ {
                go func() {
                        defer wg.Done()
                        endpoint := "localhost:9000"
                        accessKeyID := "minioadmin"
                        secretAccessKey := "minioadmin"
                        useSSL := false

                        // Initialize minio client object.
                        minioClient, err := minio.New(endpoint, &minio.Options{
                                Creds:  credentials.NewStaticV4(accessKeyID, secretAccessKey, ""),
                                Secure: useSSL,
                        })
                        if err != nil {
                                fmt.Println(err)
                                return
                        }
                        ctx := context.Background()

                        obj, err := minioClient.GetObject(ctx, "test-bucket", "issue", minio.GetObjectOptions{})
                        if err != nil {
                                fmt.Println(err)
                                return
                        }
                        defer obj.Close()
                        
                        localFile, err := os.Create("a.txt")
                        if err != nil {
                            fmt.Println(err)
                            return
                        }
                        defer localFile.Close()

                        if _, err = io.Copy(localFile, obj); err != nil {
                            fmt.Println(err)
                            return
                        }
                        fmt.Println("Read the object and copied locally")             
                }()
        }
        wg.Wait()
}

Also in case if throttle quota breach MinIO would show errors as below

API: PutObject(bucket=test-bucket, object=file392)
Time: 11:10:31 UTC 12/13/2023
DeploymentID: cd195cc1-ad90-4697-8665-1b0c15952c98
RequestID: 17A05FA750155169
RemoteHost: [::1]
Host: localhost:9000
UserAgent: MinIO (linux; amd64) minio-go/v7.0.63
Error: Throttle quota exceeded. Applied RuleID: clsp1btb4dtl7p6ad190, Allowed Requests Count: 10, Current Requets Count: 66, API: PutObject (cmd.BucketThrottleQuotaExceeded)

And MinIO trace should show details as below

localhost:9000 [REQUEST s3.PutObject] [2023-12-13T16:40:31.353] [Client IP: [::1]]
localhost:9000 PUT /test-bucket/file478
localhost:9000 Proto: HTTP/1.1
localhost:9000 Host: localhost:9000
localhost:9000 Authorization: AWS4-HMAC-SHA256 Credential=minioadmin/20231213/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length,Signature=cc131066ee54b77cc221ab31f6bd71c55675e9f81972693e9c1998cdbe6bca5f
localhost:9000 Content-Length: 201
localhost:9000 Content-Type: application/octet-stream
localhost:9000 User-Agent: MinIO (linux; amd64) minio-go/v7.0.63
localhost:9000 X-Amz-Content-Sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD
localhost:9000 X-Amz-Date: 20231213T111031Z
localhost:9000 X-Amz-Decoded-Content-Length: 28
localhost:9000 <BLOB>
localhost:9000 [RESPONSE] [2023-12-13T16:40:31.375] [ Duration 21.199ms TTFB 21.192972ms ↑ 119 B  ↓ 471 B ]
localhost:9000 400 Bad Request
localhost:9000 Content-Length: 471
localhost:9000 Content-Type: application/xml
localhost:9000 X-Amz-Id-2: dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8
localhost:9000 X-Amz-Request-Id: 17A05FA75016DC42
localhost:9000 X-Content-Type-Options: nosniff
localhost:9000 Accept-Ranges: bytes
localhost:9000 Server: MinIO
localhost:9000 Strict-Transport-Security: max-age=31536000; includeSubDomains
localhost:9000 Vary: Origin,Accept-Encoding
localhost:9000 X-Xss-Protection: 1; mode=block
localhost:9000 <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>XMinioAdminBucketThrottleQuotaExceeded</Code><Message>Throttle quota exceeded. Applied RuleID: clsp1btb4dtl7p6ad190, Allowed Requests Count: 10, Current Requets Count: 67, API: PutObject</Message><Key>file478</Key><BucketName>test-bucket</BucketName><Resource>/test-bucket/file478</Resource><RequestId>17A05FA75016DC42</RequestId><HostId>dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8</HostId></Error>

Needs minio/minio#18595, minio/madmin-go#252 and minio/console#3160

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Optimization (provides speedup with no functional changes)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • Fixes a regression (If yes, please add commit-id or PR # here)
  • Unit tests added/updated
  • Internal documentation updated
  • Create a documentation update request here

@shtripat shtripat changed the title Added command mc throttle for setting bucket throttle Enabled mc quota to set bucket throttle config Dec 5, 2023
@shtripat shtripat marked this pull request as ready for review December 5, 2023 15:26
Signed-off-by: Shubhendu Ram Tripathi <[email protected]>
Signed-off-by: Shubhendu Ram Tripathi <[email protected]>
Signed-off-by: Shubhendu Ram Tripathi <[email protected]>
@shtripat shtripat requested a review from kannappanr December 13, 2023 11:17
@shtripat
Copy link
Contributor Author

Closing as not needed.

@shtripat shtripat closed this Dec 19, 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.

1 participant