了解如何为长时间运行的操作配置轮询政策。适用于 Rust 的Google Cloud 客户端库提供了辅助函数,可简化长时间运行的操作 (LRO) 的进度监控。这些辅助程序使用政策来配置轮询频率,并确定哪些轮询错误是暂时性的(可以安全地重试),哪些是无法恢复的。
以下两项政策可控制 LRO 循环的行为:
- 轮询退避政策用于控制循环在轮询仍在进行中的 LRO 的状态之前等待的时间。
- 轮询错误政策用于控制在出现轮询错误时应执行的操作。某些轮询错误是无法恢复的,表示操作已中止或调用者无权检查 LRO 的状态。其他轮询错误是暂时性的,表示客户端网络或服务中存在临时问题。
您可以单独设置每项政策。此外,您还可以对客户端上启动的所有 LRO 应用政策,或更改单个请求的政策。
前提条件
本指南使用 Cloud Storage 服务来使代码段具体化,但相同的概念适用于使用 LRO 的任何其他服务。
在使用本指南之前,请按照将 Cloud Storage 与 Rust 搭配使用中的说明启用 Cloud Storage API 并对其进行身份验证。
如需查看 Rust 库的完整设置说明,请参阅设置开发环境。
依赖项
将以下依赖项添加到您的 Cargo.toml 文件中:
cargo add google-cloud-storage google-cloud-lro
为客户端中的所有请求配置轮询频率
如果您打算对同一客户端的大多数请求使用相同的轮询退避政策,请考虑将该政策设置为客户端选项。此代码示例会为向 Cloud Storage 服务发出的所有请求配置轮询频率。
pub async fn client_backoff(bucket: &str, folder: &str, dest: &str) -> Result<()> {
// Use a type that implements the `PollingBackoffPolicy` trait, in this case
// `ExponentialBackoffBuilder`.
use google_cloud_gax::exponential_backoff::ExponentialBackoffBuilder;
use google_cloud_lro::Poller;
use std::time::Duration;
let client = StorageControl::builder()
// Initialize the policy with a chosen delay duration.
.with_polling_backoff_policy(
ExponentialBackoffBuilder::new()
.with_initial_delay(Duration::from_millis(250))
.with_maximum_delay(Duration::from_secs(10))
.build()?,
)
.build()
.await?;
// Initiate an LRO using polling.
let response = client
.rename_folder()
.set_name(format!("projects/_/buckets/{bucket}/folders/{folder}"))
.set_destination_folder_id(dest)
.poller()
.until_done()
.await?;
println!("LRO completed, response={response:?}");
Ok(())
}
除非您使用每个请求的设置替换该政策,否则该政策将对客户端启动的任何长时间运行的操作保持有效。
例如,以下调用将使用此政策:
let mut operation = client
.rename_folder()
/* more stuff */
.send()
.await?;
在此示例调用中,客户端库在第一次轮询尝试后等待 250 毫秒,然后在第二次尝试后等待 500 毫秒。后续尝试会等待 1 秒、2 秒、4 秒和 8 秒,然后所有进一步的尝试都会等待 10 秒。
为特定请求配置轮询频率
您可以为单个请求配置轮询频率,这会替换客户端级设置的所有政策。例如:
pub async fn rpc_backoff(bucket: &str, folder: &str, dest: &str) -> Result<()> {
// Use a type that implements the `PollingBackoffPolicy` trait, in this case
// `ExponentialBackoffBuilder`.
use google_cloud_gax::exponential_backoff::ExponentialBackoffBuilder;
use std::time::Duration;
// To configure the request, bring the RequestOptionsBuilder trait into
// scope.
use google_cloud_gax::options::RequestOptionsBuilder;
use google_cloud_lro::Poller;
let client = StorageControl::builder().build().await?;
// Create the request builder.
let response = client
.rename_folder()
// Configure the polling backoff policy.
.with_polling_backoff_policy(
ExponentialBackoffBuilder::new()
.with_initial_delay(Duration::from_millis(250))
.with_maximum_delay(Duration::from_secs(10))
.build()?,
)
.set_name(format!("projects/_/buckets/{bucket}/folders/{folder}"))
.set_destination_folder_id(dest)
// Issue the polling request as normal.
.poller()
.until_done()
.await?;
println!("LRO completed, response={response:?}");
Ok(())
}
为客户端中的所有请求配置可重试的轮询错误
如需配置可重试的错误,请使用实现 PollingErrorPolicy 特征的类型。客户端库提供了多种政策;保守的选择是 Aip194Strict。如果您打算对同一客户端的大多数请求使用相同的轮询政策,请考虑将该政策设置为客户端选项。
此代码示例为对 Cloud Storage 服务的所有请求配置了可重试的轮询错误:
pub async fn client_error_policy(bucket: &str, folder: &str, dest: &str) -> Result<()> {
// Use a type that implements the `PollingErrorPolicy` trait, in this case
// `Aip194Strict`.
use google_cloud_gax::polling_error_policy::Aip194Strict;
use google_cloud_gax::polling_error_policy::PollingErrorPolicyExt;
use google_cloud_lro::Poller;
use std::time::Duration;
// Add the polling policy that you want to use for all long-running
// operations.
let client = StorageControl::builder()
.with_polling_error_policy(
Aip194Strict
.with_attempt_limit(100)
.with_time_limit(Duration::from_secs(300)),
)
.build()
.await?;
// Initiate an LRO using polling.
let response = client
.rename_folder()
.set_name(format!("projects/_/buckets/{bucket}/folders/{folder}"))
.set_destination_folder_id(dest)
.poller()
.until_done()
.await?;
println!("LRO completed, response={response:?}");
Ok(())
}
虽然轮询错误政策可以处理 LRO 等待循环期间的错误,但您也可以添加标准重试政策来处理在最初发送请求以启动 LRO 时可能发生的暂时性错误:
let client = StorageControl::builder()
.with_retry_policy(
retry_policy::Aip194Strict
.with_attempt_limit(100)
.with_time_limit(Duration::from_secs(300)),
)
.build()
.await?;
除非您使用按请求设置替换该政策,否则该政策将对客户端启动的任何长时间运行的操作保持有效。例如,如果您进行以下调用:
let mut operation = client
.rename_folder()
/* more stuff */
.send()
.await?;
注意:客户端库仅将 UNAVAILABLE(请参阅 AIP-194)视为可重试的错误,并在尝试 100 次或 300 秒后(以先到者为准)停止轮询。
为特定请求配置可重试的轮询错误
您可以使用实现 PollingErrorPolicy 特征的类型,并将 RequestOptionsBuilder 特征纳入范围,为特定请求配置可重试的轮询错误。
此代码示例为向 Cloud Storage 服务发出的特定请求配置了可重试的轮询错误。
pub async fn rpc_error_policy(bucket: &str, folder: &str, dest: &str) -> Result<()> {
// Use a type that implements the `PollingErrorPolicy` trait, in this case
// `Aip194Strict`.
use google_cloud_gax::polling_error_policy::Aip194Strict;
use google_cloud_gax::polling_error_policy::PollingErrorPolicyExt;
// Bring `RequestOptionsBuilder` into scope.
use google_cloud_gax::options::RequestOptionsBuilder;
use std::time::Duration;
use google_cloud_lro::Poller;
let client = StorageControl::builder().build().await?;
// Create the request builder.
let response = client
.rename_folder()
// Configure the polling error policy.
.with_polling_error_policy(
Aip194Strict
.with_attempt_limit(100)
.with_time_limit(Duration::from_secs(300)),
)
.set_name(format!("projects/_/buckets/{bucket}/folders/{folder}"))
.set_destination_folder_id(dest)
// Initialize the request.
.poller()
.until_done()
.await?;
println!("LRO completed, response={response:?}");
Ok(())
}
您还可以考虑添加重试政策,以防启动 LRO 的初始请求失败:
let client = StorageControl::builder()
.with_retry_policy(
retry_policy::Aip194Strict
.with_attempt_limit(100)
.with_time_limit(Duration::from_secs(300)),
)
.build()
.await?;