Skip to content

Commit 865c778

Browse files
chlinssuhan.zcy
andauthored
feat: support the rate limit for preheat request (#881)
Signed-off-by: chlins <[email protected]> Co-authored-by: suhan.zcy <[email protected]>
1 parent d8f0931 commit 865c778

File tree

9 files changed

+100
-30
lines changed

9 files changed

+100
-30
lines changed

Cargo.lock

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ members = [
1212
]
1313

1414
[workspace.package]
15-
version = "0.1.123"
15+
version = "0.1.124"
1616
authors = ["The Dragonfly Developers"]
1717
homepage = "https://d7y.io/"
1818
repository = "https://github.com/dragonflyoss/client.git"
@@ -22,16 +22,25 @@ readme = "README.md"
2222
edition = "2021"
2323

2424
[workspace.dependencies]
25-
dragonfly-client = { path = "dragonfly-client", version = "0.1.123" }
26-
dragonfly-client-core = { path = "dragonfly-client-core", version = "0.1.123" }
27-
dragonfly-client-config = { path = "dragonfly-client-config", version = "0.1.123" }
28-
dragonfly-client-storage = { path = "dragonfly-client-storage", version = "0.1.123" }
29-
dragonfly-client-backend = { path = "dragonfly-client-backend", version = "0.1.123" }
30-
dragonfly-client-util = { path = "dragonfly-client-util", version = "0.1.123" }
31-
dragonfly-client-init = { path = "dragonfly-client-init", version = "0.1.123" }
25+
dragonfly-client = { path = "dragonfly-client", version = "0.1.124" }
26+
dragonfly-client-core = { path = "dragonfly-client-core", version = "0.1.124" }
27+
dragonfly-client-config = { path = "dragonfly-client-config", version = "0.1.124" }
28+
dragonfly-client-storage = { path = "dragonfly-client-storage", version = "0.1.124" }
29+
dragonfly-client-backend = { path = "dragonfly-client-backend", version = "0.1.124" }
30+
dragonfly-client-util = { path = "dragonfly-client-util", version = "0.1.124" }
31+
dragonfly-client-init = { path = "dragonfly-client-init", version = "0.1.124" }
3232
thiserror = "1.0"
33-
dragonfly-api = "=2.0.173"
34-
reqwest = { version = "0.12.4", features = ["stream", "native-tls", "default-tls", "rustls-tls", "gzip", "brotli", "zstd", "deflate"] }
33+
dragonfly-api = "=2.0.174"
34+
reqwest = { version = "0.12.4", features = [
35+
"stream",
36+
"native-tls",
37+
"default-tls",
38+
"rustls-tls",
39+
"gzip",
40+
"brotli",
41+
"zstd",
42+
"deflate",
43+
] }
3544
reqwest-middleware = "0.4"
3645
rcgen = { version = "0.12.1", features = ["x509-parser"] }
3746
hyper = { version = "1.5", features = ["full"] }

dragonfly-client-config/src/dfdaemon.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,14 @@ pub fn default_proxy_read_buffer_size() -> usize {
225225
32 * 1024
226226
}
227227

228+
/// default_prefetch_rate_limit is the default rate limit of the prefetch speed in GiB/Mib/Kib per second.
229+
/// The prefetch request has lower priority so limit the rate to avoid occupying the bandwidth impact other download tasks.
230+
#[inline]
231+
fn default_prefetch_rate_limit() -> ByteSize {
232+
// Default rate limit is 2GiB/s.
233+
ByteSize::gib(2)
234+
}
235+
228236
/// default_s3_filtered_query_params is the default filtered query params with s3 protocol to generate the task id.
229237
#[inline]
230238
fn s3_filtered_query_params() -> Vec<String> {
@@ -1089,6 +1097,10 @@ pub struct Proxy {
10891097
/// prefetch pre-downloads full of the task when download with range request.
10901098
pub prefetch: bool,
10911099

1100+
/// rate_limit is the rate limit of the prefetch speed in GiB/Mib/Kib per second.
1101+
#[serde(with = "bytesize_serde", default = "default_prefetch_rate_limit")]
1102+
pub prefetch_rate_limit: ByteSize,
1103+
10921104
/// cache_capacity is the capacity of the cache by LRU algorithm for HTTP proxy, default is 150.
10931105
/// The cache is used to store the hot piece content of the task, piece length is 4MB~16MB.
10941106
/// If the capacity is 150, the cache size is 600MB~2.4GB, need to adjust according to the
@@ -1110,6 +1122,7 @@ impl Default for Proxy {
11101122
registry_mirror: RegistryMirror::default(),
11111123
disable_back_to_source: false,
11121124
prefetch: false,
1125+
prefetch_rate_limit: default_prefetch_rate_limit(),
11131126
cache_capacity: default_proxy_cache_capacity(),
11141127
read_buffer_size: default_proxy_read_buffer_size(),
11151128
}

dragonfly-client/src/bin/dfget/main.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,19 @@ Examples:
6161
6262
# Download a file from Amazon Simple Storage Service(S3).
6363
$ dfget s3://<bucket>/<path> -O /tmp/file.txt --storage-access-key-id=<access_key_id> --storage-access-key-secret=<access_key_secret>
64-
64+
6565
# Download a file from Google Cloud Storage Service(GCS).
6666
$ dfget gs://<bucket>/<path> -O /tmp/file.txt --storage-credential-path=<credential_path>
67-
67+
6868
# Download a file from Azure Blob Storage Service(ABS).
6969
$ dfget abs://<container>/<path> -O /tmp/file.txt --storage-access-key-id=<account_name> --storage-access-key-secret=<account_key>
70-
70+
7171
# Download a file from Aliyun Object Storage Service(OSS).
7272
$ dfget oss://<bucket>/<path> -O /tmp/file.txt --storage-access-key-id=<access_key_id> --storage-access-key-secret=<access_key_secret> --storage-endpoint=<endpoint>
73-
73+
7474
# Download a file from Huawei Cloud Object Storage Service(OBS).
7575
$ dfget obs://<bucket>/<path> -O /tmp/file.txt --storage-access-key-id=<access_key_id> --storage-access-key-secret=<access_key_secret> --storage-endpoint=<endpoint>
76-
76+
7777
# Download a file from Tencent Cloud Object Storage Service(COS).
7878
$ dfget cos://<bucket>/<path> -O /tmp/file.txt --storage-access-key-id=<access_key_id> --storage-access-key-secret=<access_key_secret> --storage-endpoint=<endpoint>
7979
"#;
@@ -738,6 +738,7 @@ async fn download(
738738
disable_back_to_source: args.disable_back_to_source,
739739
certificate_chain: Vec::new(),
740740
prefetch: false,
741+
is_prefetch: false,
741742
object_storage,
742743
hdfs,
743744
}),

dragonfly-client/src/grpc/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ pub async fn prefetch_task(
7777
// Remove the prefetch flag for prevent the infinite loop.
7878
download.prefetch = false;
7979

80+
// Mark the is_prefetch flag as true to represents it is a prefetch request.
81+
download.is_prefetch = true;
82+
8083
// Remove the range header for download full task.
8184
download
8285
.request_header

dragonfly-client/src/proxy/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,7 @@ async fn proxy_via_dfdaemon(
831831
piece.length,
832832
download_task_started_response.range,
833833
true,
834+
false,
834835
)
835836
.await
836837
{
@@ -1089,6 +1090,7 @@ fn make_download_task_request(
10891090
prefetch: need_prefetch(config.clone(), &header),
10901091
object_storage: None,
10911092
hdfs: None,
1093+
is_prefetch: false,
10921094
}),
10931095
})
10941096
}

dragonfly-client/src/resource/persistent_cache_task.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,7 @@ impl PersistentCacheTask {
856856
number,
857857
length,
858858
parent.clone(),
859+
false,
859860
)
860861
.await
861862
.map_err(|err| {

dragonfly-client/src/resource/piece.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ pub struct Piece {
7474

7575
/// upload_rate_limiter is the rate limiter of the upload speed in bps(bytes per second).
7676
upload_rate_limiter: Arc<RateLimiter>,
77+
78+
/// prefetch_rate_limiter is the rate limiter of the prefetch speed in bps(bytes per second).
79+
prefetch_rate_limiter: Arc<RateLimiter>,
7780
}
7881

7982
/// Piece implements the piece manager.
@@ -106,6 +109,13 @@ impl Piece {
106109
.interval(Duration::from_secs(1))
107110
.build(),
108111
),
112+
prefetch_rate_limiter: Arc::new(
113+
RateLimiter::builder()
114+
.initial(config.proxy.prefetch_rate_limit.as_u64() as usize)
115+
.refill(config.proxy.prefetch_rate_limit.as_u64() as usize)
116+
.interval(Duration::from_secs(1))
117+
.build(),
118+
),
109119
}
110120
}
111121

@@ -343,13 +353,20 @@ impl Piece {
343353
length: u64,
344354
range: Option<Range>,
345355
disable_rate_limit: bool,
356+
is_prefetch: bool,
346357
) -> Result<impl AsyncRead> {
347358
// Span record the piece_id.
348359
Span::current().record("piece_id", piece_id);
349360

350361
// Acquire the download rate limiter.
351362
if !disable_rate_limit {
352-
self.download_rate_limiter.acquire(length as usize).await;
363+
if is_prefetch {
364+
// Acquire the prefetch rate limiter.
365+
self.prefetch_rate_limiter.acquire(length as usize).await;
366+
} else {
367+
// Acquire the download rate limiter.
368+
self.download_rate_limiter.acquire(length as usize).await;
369+
}
353370
}
354371

355372
// Upload the piece content.
@@ -368,6 +385,7 @@ impl Piece {
368385
}
369386

370387
/// download_from_remote_peer downloads a single piece from a remote peer.
388+
#[allow(clippy::too_many_arguments)]
371389
#[instrument(skip_all, fields(piece_id))]
372390
pub async fn download_from_remote_peer(
373391
&self,
@@ -377,12 +395,18 @@ impl Piece {
377395
number: u32,
378396
length: u64,
379397
parent: piece_collector::CollectedParent,
398+
is_prefetch: bool,
380399
) -> Result<metadata::Piece> {
381400
// Span record the piece_id.
382401
Span::current().record("piece_id", piece_id);
383402

384-
// Acquire the download rate limiter.
385-
self.download_rate_limiter.acquire(length as usize).await;
403+
if is_prefetch {
404+
// Acquire the prefetch rate limiter.
405+
self.prefetch_rate_limiter.acquire(length as usize).await;
406+
} else {
407+
// Acquire the download rate limiter.
408+
self.download_rate_limiter.acquire(length as usize).await;
409+
}
386410

387411
// Record the start of downloading piece.
388412
let piece = self
@@ -506,14 +530,20 @@ impl Piece {
506530
offset: u64,
507531
length: u64,
508532
request_header: HeaderMap,
533+
is_prefetch: bool,
509534
object_storage: Option<ObjectStorage>,
510535
hdfs: Option<Hdfs>,
511536
) -> Result<metadata::Piece> {
512537
// Span record the piece_id.
513538
Span::current().record("piece_id", piece_id);
514539

515-
// Acquire the download rate limiter.
516-
self.download_rate_limiter.acquire(length as usize).await;
540+
if is_prefetch {
541+
// Acquire the prefetch rate limiter.
542+
self.prefetch_rate_limiter.acquire(length as usize).await;
543+
} else {
544+
// Acquire the download rate limiter.
545+
self.download_rate_limiter.acquire(length as usize).await;
546+
}
517547

518548
// Record the start of downloading piece.
519549
let piece = self

0 commit comments

Comments
 (0)