Line data Source code
1 : #pragma once 2 : 3 : #include <cstdint> 4 : #include <string> 5 : 6 : #include "envoy/common/random_generator.h" 7 : #include "envoy/event/timer.h" 8 : #include "envoy/http/codec.h" 9 : #include "envoy/http/header_map.h" 10 : #include "envoy/router/context.h" 11 : #include "envoy/router/router.h" 12 : #include "envoy/runtime/runtime.h" 13 : #include "envoy/upstream/upstream.h" 14 : 15 : #include "source/common/common/backoff_strategy.h" 16 : #include "source/common/http/header_utility.h" 17 : 18 : #include "absl/strings/string_view.h" 19 : #include "absl/types/optional.h" 20 : 21 : namespace Envoy { 22 : namespace Router { 23 : 24 : /** 25 : * Wraps retry state for the router. 26 : */ 27 : class RetryStateImpl : public RetryState { 28 : public: 29 : static std::unique_ptr<RetryStateImpl> 30 : create(const RetryPolicy& route_policy, Http::RequestHeaderMap& request_headers, 31 : const Upstream::ClusterInfo& cluster, const VirtualCluster* vcluster, 32 : RouteStatsContextOptRef route_stats_context, Runtime::Loader& runtime, 33 : Random::RandomGenerator& random, Event::Dispatcher& dispatcher, TimeSource& time_source, 34 : Upstream::ResourcePriority priority); 35 : ~RetryStateImpl() override; 36 : 37 : /** 38 : * Returns the RetryPolicy extracted from the x-envoy-retry-on header. 39 : * @param config is the value of the header. 40 : * @return std::pair<uint32_t, bool> the uint32_t is a bitset representing the 41 : * valid retry policies in @param config. The bool is TRUE iff all the 42 : * policies specified in @param config are valid. 43 : */ 44 : static std::pair<uint32_t, bool> parseRetryOn(absl::string_view config); 45 : 46 : /** 47 : * Returns the RetryPolicy extracted from the x-envoy-retry-grpc-on header. 48 : * @param config is the value of the header. 49 : * @return std::pair<uint32_t, bool> the uint32_t is a bitset representing the 50 : * valid retry policies in @param config. The bool is TRUE iff all the 51 : * policies specified in @param config are valid. 52 : */ 53 : static std::pair<uint32_t, bool> parseRetryGrpcOn(absl::string_view retry_grpc_on_header); 54 : 55 : // Router::RetryState 56 0 : bool enabled() override { return retry_on_ != 0; } 57 : absl::optional<std::chrono::milliseconds> 58 : parseResetInterval(const Http::ResponseHeaderMap& response_headers) const override; 59 : RetryStatus shouldRetryHeaders(const Http::ResponseHeaderMap& response_headers, 60 : const Http::RequestHeaderMap& original_request, 61 : DoRetryHeaderCallback callback) override; 62 : // Returns if the retry policy would retry the passed headers and how. Does not 63 : // take into account circuit breaking or remaining tries. 64 : RetryDecision wouldRetryFromHeaders(const Http::ResponseHeaderMap& response_headers, 65 : const Http::RequestHeaderMap& original_request, 66 : bool& disable_early_data) override; 67 : RetryStatus shouldRetryReset(Http::StreamResetReason reset_reason, Http3Used http3_used, 68 : DoRetryResetCallback callback) override; 69 : RetryStatus shouldHedgeRetryPerTryTimeout(DoRetryCallback callback) override; 70 : 71 0 : void onHostAttempted(Upstream::HostDescriptionConstSharedPtr host) override { 72 0 : std::for_each(retry_host_predicates_.begin(), retry_host_predicates_.end(), 73 0 : [&host](auto predicate) { predicate->onHostAttempted(host); }); 74 0 : if (retry_priority_) { 75 0 : retry_priority_->onHostAttempted(host); 76 0 : } 77 0 : } 78 : 79 0 : bool shouldSelectAnotherHost(const Upstream::Host& host) override { 80 0 : return std::any_of( 81 0 : retry_host_predicates_.begin(), retry_host_predicates_.end(), 82 0 : [&host](auto predicate) { return predicate->shouldSelectAnotherHost(host); }); 83 0 : } 84 : 85 : const Upstream::HealthyAndDegradedLoad& priorityLoadForRetry( 86 : const Upstream::PrioritySet& priority_set, 87 : const Upstream::HealthyAndDegradedLoad& original_priority_load, 88 0 : const Upstream::RetryPriority::PriorityMappingFunc& priority_mapping_func) override { 89 0 : if (!retry_priority_) { 90 0 : return original_priority_load; 91 0 : } 92 0 : return retry_priority_->determinePriorityLoad(priority_set, original_priority_load, 93 0 : priority_mapping_func); 94 0 : } 95 : 96 0 : uint32_t hostSelectionMaxAttempts() const override { return host_selection_max_attempts_; } 97 : 98 0 : bool isAutomaticallyConfiguredForHttp3() const { return auto_configured_for_http3_; } 99 : 100 : private: 101 : RetryStateImpl(const RetryPolicy& route_policy, Http::RequestHeaderMap& request_headers, 102 : const Upstream::ClusterInfo& cluster, const VirtualCluster* vcluster, 103 : RouteStatsContextOptRef route_stats_context, Runtime::Loader& runtime, 104 : Random::RandomGenerator& random, Event::Dispatcher& dispatcher, 105 : TimeSource& time_source, Upstream::ResourcePriority priority, 106 : bool auto_configured_for_http3); 107 : 108 : void enableBackoffTimer(); 109 : void resetRetry(); 110 : // Returns if the retry policy would retry the reset and how. Does not 111 : // take into account circuit breaking or remaining tries. 112 : // disable_http3: populated to tell the caller whether to disable http3 or not when the return 113 : // value indicates retry. 114 : RetryDecision wouldRetryFromReset(const Http::StreamResetReason reset_reason, 115 : Http3Used http3_used, bool& disable_http3); 116 : RetryStatus shouldRetry(RetryDecision would_retry, DoRetryCallback callback); 117 : 118 : const Upstream::ClusterInfo& cluster_; 119 : const VirtualCluster* vcluster_; 120 : RouteStatsContextOptRef route_stats_context_; 121 : Runtime::Loader& runtime_; 122 : Random::RandomGenerator& random_; 123 : Event::Dispatcher& dispatcher_; 124 : TimeSource& time_source_; 125 : DoRetryCallback backoff_callback_; 126 : Event::SchedulableCallbackPtr next_loop_callback_; 127 : Event::TimerPtr retry_timer_; 128 : BackOffStrategyPtr backoff_strategy_; 129 : BackOffStrategyPtr ratelimited_backoff_strategy_{}; 130 : std::vector<Upstream::RetryHostPredicateSharedPtr> retry_host_predicates_; 131 : Upstream::RetryPrioritySharedPtr retry_priority_; 132 : std::vector<uint32_t> retriable_status_codes_; 133 : std::vector<Http::HeaderMatcherSharedPtr> retriable_headers_; 134 : std::vector<ResetHeaderParserSharedPtr> reset_headers_{}; 135 : std::chrono::milliseconds reset_max_interval_{}; 136 : 137 : // Keep small members (bools, enums and int32s) at the end of class, to reduce alignment overhead. 138 : uint32_t retry_on_{}; 139 : uint32_t retries_remaining_{}; 140 : uint32_t host_selection_max_attempts_; 141 : Upstream::ResourcePriority priority_; 142 : const bool auto_configured_for_http3_{}; 143 : }; 144 : 145 : } // namespace Router 146 : } // namespace Envoy