This is an automated email from the ASF dual-hosted git repository.

gavinchou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 529ba615039 [Improvement](ObjectStorage) Retry when encountering 
TooManyRequest response (#37199)
529ba615039 is described below

commit 529ba615039d915a5956bf40418aa450ce6042ef
Author: AlexYue <yj976240...@gmail.com>
AuthorDate: Thu Jul 18 11:43:16 2024 +0800

    [Improvement](ObjectStorage) Retry when encountering TooManyRequest 
response (#37199)
    
    We can do retry for 429 using the embedded utility of corresponding sdk.
---
 cloud/src/recycler/s3_accessor.cpp | 29 +++++-------------
 common/cpp/obj_retry_strategy.cpp  | 61 ++++++++++++++++++++++++++++++++++++++
 common/cpp/obj_retry_strategy.h    | 48 ++++++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 21 deletions(-)

diff --git a/cloud/src/recycler/s3_accessor.cpp 
b/cloud/src/recycler/s3_accessor.cpp
index c5b312fa2d3..54869a14b52 100644
--- a/cloud/src/recycler/s3_accessor.cpp
+++ b/cloud/src/recycler/s3_accessor.cpp
@@ -36,32 +36,13 @@
 #include "common/logging.h"
 #include "common/string_util.h"
 #include "common/util.h"
+#include "cpp/obj_retry_strategy.h"
 #include "cpp/s3_rate_limiter.h"
 #include "recycler/azure_obj_client.h"
 #include "recycler/obj_storage_client.h"
 #include "recycler/s3_obj_client.h"
 #include "recycler/storage_vault_accessor.h"
 
-namespace {
-
-bvar::Adder<uint64_t> 
too_many_request_http_retry_times("too_many_request_http_retry_times");
-
-class CustomRetryStrategy final : public Aws::Client::DefaultRetryStrategy {
-public:
-    CustomRetryStrategy(int maxRetries) : DefaultRetryStrategy(maxRetries) {}
-
-    bool ShouldRetry(const Aws::Client::AWSError<Aws::Client::CoreErrors>& 
error,
-                     long attemptedRetries) const override {
-        if (attemptedRetries < m_maxRetries &&
-            error.GetResponseCode() == 
Aws::Http::HttpResponseCode::TOO_MANY_REQUESTS) {
-            too_many_request_http_retry_times << 1;
-            return true;
-        }
-        return Aws::Client::DefaultRetryStrategy::ShouldRetry(error, 
attemptedRetries);
-    }
-};
-} // namespace
-
 namespace doris::cloud {
 bvar::Adder<int64_t> get_rate_limit_ms("get_rate_limit_ms");
 bvar::Adder<int64_t> put_rate_limit_ms("put_rate_limit_ms");
@@ -229,6 +210,12 @@ int S3Accessor::init() {
                 
std::make_shared<Azure::Storage::StorageSharedKeyCredential>(conf_.ak, 
conf_.sk);
         uri_ = fmt::format("{}://{}.blob.core.windows.net/{}", 
config::s3_client_http_scheme,
                            conf_.ak, conf_.bucket);
+        // In Azure's HTTP requests, all policies in the vector are called in 
a chained manner following the HTTP pipeline approach.
+        // Within the RetryPolicy, the nextPolicy is called multiple times 
inside a loop.
+        // All policies in the PerRetryPolicies are downstream of the 
RetryPolicy.
+        // Therefore, you only need to add a policy to check if the response 
code is 429 and if the retry count meets the condition, it can record the retry 
count.
+        options.PerRetryPolicies.emplace_back(
+                
std::make_unique<AzureRetryRecordPolicy>(config::max_s3_client_retry));
         auto container_client = 
std::make_shared<Azure::Storage::Blobs::BlobContainerClient>(
                 uri_, cred, std::move(options));
         // uri format for debug: 
${scheme}://${ak}.blob.core.windows.net/${bucket}/${prefix}
@@ -249,7 +236,7 @@ int S3Accessor::init() {
         if (config::s3_client_http_scheme == "http") {
             aws_config.scheme = Aws::Http::Scheme::HTTP;
         }
-        aws_config.retryStrategy = std::make_shared<CustomRetryStrategy>(
+        aws_config.retryStrategy = std::make_shared<S3CustomRetryStrategy>(
                 config::max_s3_client_retry /*scaleFactor = 25*/);
         auto s3_client = std::make_shared<Aws::S3::S3Client>(
                 std::move(aws_cred), std::move(aws_config),
diff --git a/common/cpp/obj_retry_strategy.cpp 
b/common/cpp/obj_retry_strategy.cpp
new file mode 100644
index 00000000000..8461ab39f74
--- /dev/null
+++ b/common/cpp/obj_retry_strategy.cpp
@@ -0,0 +1,61 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "obj_retry_strategy.h"
+
+#include <bvar/reducer.h>
+
+namespace doris {
+
+bvar::Adder<int64_t> 
s3_too_many_request_retry_cnt("s3_too_many_request_retry_cnt");
+
+S3CustomRetryStrategy::S3CustomRetryStrategy(int maxRetries) : 
DefaultRetryStrategy(maxRetries) {}
+
+S3CustomRetryStrategy::~S3CustomRetryStrategy() = default;
+
+bool S3CustomRetryStrategy::ShouldRetry(const 
Aws::Client::AWSError<Aws::Client::CoreErrors>& error,
+                                        long attemptedRetries) const {
+    if (attemptedRetries < m_maxRetries &&
+        error.GetResponseCode() == 
Aws::Http::HttpResponseCode::TOO_MANY_REQUESTS) {
+        s3_too_many_request_retry_cnt << 1;
+        return true;
+    }
+    return Aws::Client::DefaultRetryStrategy::ShouldRetry(error, 
attemptedRetries);
+}
+
+AzureRetryRecordPolicy::AzureRetryRecordPolicy(int retry_cnt) : 
retry_cnt(retry_cnt) {}
+
+AzureRetryRecordPolicy::~AzureRetryRecordPolicy() = default;
+
+std::unique_ptr<Azure::Core::Http::RawResponse> AzureRetryRecordPolicy::Send(
+        Azure::Core::Http::Request& request, 
Azure::Core::Http::Policies::NextHttpPolicy nextPolicy,
+        Azure::Core::Context const& context) const {
+    auto resp = nextPolicy.Send(request, context);
+    if (retry_cnt != 0 &&
+        resp->GetStatusCode() == 
Azure::Core::Http::HttpStatusCode::TooManyRequests) {
+        retry_cnt--;
+        s3_too_many_request_retry_cnt << 1;
+    }
+    return resp;
+}
+
+std::unique_ptr<AzureRetryRecordPolicy::HttpPolicy> 
AzureRetryRecordPolicy::Clone() const {
+    auto ret = std::make_unique<AzureRetryRecordPolicy>(*this);
+    ret->retry_cnt = 0;
+    return ret;
+}
+} // namespace doris
\ No newline at end of file
diff --git a/common/cpp/obj_retry_strategy.h b/common/cpp/obj_retry_strategy.h
new file mode 100644
index 00000000000..181762ffdf2
--- /dev/null
+++ b/common/cpp/obj_retry_strategy.h
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <aws/core/client/AWSError.h>
+#include <aws/core/client/DefaultRetryStrategy.h>
+
+#include <azure/core/http/policies/policy.hpp>
+
+namespace doris {
+class S3CustomRetryStrategy final : public Aws::Client::DefaultRetryStrategy {
+public:
+    S3CustomRetryStrategy(int maxRetries);
+    ~S3CustomRetryStrategy() override;
+
+    bool ShouldRetry(const Aws::Client::AWSError<Aws::Client::CoreErrors>& 
error,
+                     long attemptedRetries) const override;
+};
+
+class AzureRetryRecordPolicy final : public 
Azure::Core::Http::Policies::HttpPolicy {
+public:
+    AzureRetryRecordPolicy(int retry_cnt);
+    ~AzureRetryRecordPolicy() override;
+    std::unique_ptr<HttpPolicy> Clone() const override;
+    std::unique_ptr<Azure::Core::Http::RawResponse> Send(
+            Azure::Core::Http::Request& request,
+            Azure::Core::Http::Policies::NextHttpPolicy nextPolicy,
+            Azure::Core::Context const& context) const override;
+
+private:
+    mutable int retry_cnt;
+};
+} // namespace doris
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to