Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: net/base/backoff_entry.cc

Issue 6966038: Anti-DDoS enhancements: Log to net log, UMA stats, improved policy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge to head. Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/backoff_entry.h ('k') | net/base/backoff_entry_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/backoff_entry.h" 5 #include "net/base/backoff_entry.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/rand_util.h" 11 #include "base/rand_util.h"
12 12
13 namespace net { 13 namespace net {
14 14
15 BackoffEntry::BackoffEntry(const BackoffEntry::Policy* const policy) 15 BackoffEntry::BackoffEntry(const BackoffEntry::Policy* const policy)
16 : failure_count_(0), 16 : policy_(policy) {
17 policy_(policy) {
18 DCHECK(policy_); 17 DCHECK(policy_);
19 18 Reset();
20 // Can't use GetTimeNow() as it's virtual.
21 exponential_backoff_release_time_ = base::TimeTicks::Now();
22 } 19 }
23 20
24 BackoffEntry::~BackoffEntry() { 21 BackoffEntry::~BackoffEntry() {
25 // TODO(joi): Remove this once our clients (e.g. URLRequestThrottlerManager) 22 // TODO(joi): Remove this once our clients (e.g. URLRequestThrottlerManager)
26 // always destroy from the I/O thread. 23 // always destroy from the I/O thread.
27 DetachFromThread(); 24 DetachFromThread();
28 } 25 }
29 26
30 void BackoffEntry::InformOfRequest(bool succeeded) { 27 void BackoffEntry::InformOfRequest(bool succeeded) {
31 if (!succeeded) { 28 if (!succeeded) {
32 ++failure_count_; 29 ++failure_count_;
33 exponential_backoff_release_time_ = CalculateReleaseTime(); 30 exponential_backoff_release_time_ = CalculateReleaseTime();
34 } else { 31 } else {
35 // We slowly decay the number of times delayed instead of resetting it to 0 32 // We slowly decay the number of times delayed instead of resetting it to 0
36 // in order to stay stable if we receive successes interleaved between lots 33 // in order to stay stable if we receive successes interleaved between lots
37 // of failures. 34 // of failures.
38 // 35 //
39 // TODO(joi): Revisit this; it might be most correct to go to zero 36 // TODO(joi): Revisit this; it might be most correct to go to zero
40 // but have a way to go back to "old error count +1" if there is 37 // but have a way to go back to "old error count +1" if there is
41 // another error soon after. 38 // another error soon after.
42 if (failure_count_ > 0) 39 if (failure_count_ > 0)
43 --failure_count_; 40 --failure_count_;
44 41
45 // The reason why we are not just cutting the release time to GetTimeNow() 42 // The reason why we are not just cutting the release time to
46 // is on the one hand, it would unset a release time set by 43 // ImplGetTimeNow() is on the one hand, it would unset a release
47 // SetCustomReleaseTime and on the other we would like to push every 44 // time set by SetCustomReleaseTime and on the other we would like
48 // request up to our "horizon" when dealing with multiple in-flight 45 // to push every request up to our "horizon" when dealing with
49 // requests. Ex: If we send three requests and we receive 2 failures and 46 // multiple in-flight requests. Ex: If we send three requests and
50 // 1 success. The success that follows those failures will not reset the 47 // we receive 2 failures and 1 success. The success that follows
51 // release time, further requests will then need to wait the delay caused 48 // those failures will not reset the release time, further
52 // by the 2 failures. 49 // requests will then need to wait the delay caused by the 2
50 // failures.
53 exponential_backoff_release_time_ = std::max( 51 exponential_backoff_release_time_ = std::max(
54 GetTimeNow(), exponential_backoff_release_time_); 52 ImplGetTimeNow(), exponential_backoff_release_time_);
55 } 53 }
56 } 54 }
57 55
58 bool BackoffEntry::ShouldRejectRequest() const { 56 bool BackoffEntry::ShouldRejectRequest() const {
59 return exponential_backoff_release_time_ > GetTimeNow(); 57 return exponential_backoff_release_time_ > ImplGetTimeNow();
60 } 58 }
61 59
62 base::TimeTicks BackoffEntry::GetReleaseTime() const { 60 base::TimeTicks BackoffEntry::GetReleaseTime() const {
63 return exponential_backoff_release_time_; 61 return exponential_backoff_release_time_;
64 } 62 }
65 63
66 void BackoffEntry::SetCustomReleaseTime(const base::TimeTicks& release_time) { 64 void BackoffEntry::SetCustomReleaseTime(const base::TimeTicks& release_time) {
67 exponential_backoff_release_time_ = release_time; 65 exponential_backoff_release_time_ = release_time;
68 } 66 }
69 67
70 bool BackoffEntry::CanDiscard() const { 68 bool BackoffEntry::CanDiscard() const {
71 if (policy_->entry_lifetime_ms == -1) 69 if (policy_->entry_lifetime_ms == -1)
72 return false; 70 return false;
73 71
74 base::TimeTicks now = GetTimeNow(); 72 base::TimeTicks now = ImplGetTimeNow();
75 73
76 int64 unused_since_ms = 74 int64 unused_since_ms =
77 (now - exponential_backoff_release_time_).InMilliseconds(); 75 (now - exponential_backoff_release_time_).InMilliseconds();
78 76
79 // Release time is further than now, we are managing it. 77 // Release time is further than now, we are managing it.
80 if (unused_since_ms < 0) 78 if (unused_since_ms < 0)
81 return false; 79 return false;
82 80
83 if (failure_count_ > 0) { 81 if (failure_count_ > 0) {
84 // Need to keep track of failures until maximum back-off period 82 // Need to keep track of failures until maximum back-off period
85 // has passed (since further failures can add to back-off). 83 // has passed (since further failures can add to back-off).
86 return unused_since_ms >= std::max(policy_->maximum_backoff_ms, 84 return unused_since_ms >= std::max(policy_->maximum_backoff_ms,
87 policy_->entry_lifetime_ms); 85 policy_->entry_lifetime_ms);
88 } 86 }
89 87
90 // Otherwise, consider the entry is outdated if it hasn't been used for the 88 // Otherwise, consider the entry is outdated if it hasn't been used for the
91 // specified lifetime period. 89 // specified lifetime period.
92 return unused_since_ms >= policy_->entry_lifetime_ms; 90 return unused_since_ms >= policy_->entry_lifetime_ms;
93 } 91 }
94 92
95 base::TimeTicks BackoffEntry::GetTimeNow() const { 93 void BackoffEntry::Reset() {
94 failure_count_ = 0;
95
96 // We leave exponential_backoff_release_time_ unset, meaning 0. We could
97 // initialize to ImplGetTimeNow() but because it's a virtual method it's
98 // not safe to call in the constructor (and the constructor calls Reset()).
99 // The effects are the same, i.e. ShouldRejectRequest() will return false
100 // right after Reset().
101 exponential_backoff_release_time_ = base::TimeTicks();
102 }
103
104 base::TimeTicks BackoffEntry::ImplGetTimeNow() const {
96 return base::TimeTicks::Now(); 105 return base::TimeTicks::Now();
97 } 106 }
98 107
99 base::TimeTicks BackoffEntry::CalculateReleaseTime() const { 108 base::TimeTicks BackoffEntry::CalculateReleaseTime() const {
100 int effective_failure_count = 109 int effective_failure_count =
101 std::max(0, failure_count_ - policy_->num_errors_to_ignore); 110 std::max(0, failure_count_ - policy_->num_errors_to_ignore);
102 if (effective_failure_count == 0) { 111 if (effective_failure_count == 0) {
103 // Never reduce previously set release horizon, e.g. due to Retry-After 112 // Never reduce previously set release horizon, e.g. due to Retry-After
104 // header. 113 // header.
105 return std::max(GetTimeNow(), exponential_backoff_release_time_); 114 return std::max(ImplGetTimeNow(), exponential_backoff_release_time_);
106 } 115 }
107 116
108 // The delay is calculated with this formula: 117 // The delay is calculated with this formula:
109 // delay = initial_backoff * multiply_factor^( 118 // delay = initial_backoff * multiply_factor^(
110 // effective_failure_count - 1) * Uniform(1 - jitter_factor, 1] 119 // effective_failure_count - 1) * Uniform(1 - jitter_factor, 1]
111 double delay = policy_->initial_backoff_ms; 120 double delay = policy_->initial_backoff_ms;
112 delay *= pow(policy_->multiply_factor, effective_failure_count - 1); 121 delay *= pow(policy_->multiply_factor, effective_failure_count - 1);
113 delay -= base::RandDouble() * policy_->jitter_factor * delay; 122 delay -= base::RandDouble() * policy_->jitter_factor * delay;
114 123
115 // Ensure that we do not exceed maximum delay. 124 // Ensure that we do not exceed maximum delay.
116 int64 delay_int = static_cast<int64>(delay + 0.5); 125 int64 delay_int = static_cast<int64>(delay + 0.5);
117 delay_int = std::min(delay_int, 126 delay_int = std::min(delay_int,
118 static_cast<int64>(policy_->maximum_backoff_ms)); 127 static_cast<int64>(policy_->maximum_backoff_ms));
119 128
120 // Never reduce previously set release horizon, e.g. due to Retry-After 129 // Never reduce previously set release horizon, e.g. due to Retry-After
121 // header. 130 // header.
122 return std::max(GetTimeNow() + base::TimeDelta::FromMilliseconds(delay_int), 131 return std::max(
123 exponential_backoff_release_time_); 132 ImplGetTimeNow() + base::TimeDelta::FromMilliseconds(delay_int),
133 exponential_backoff_release_time_);
124 } 134 }
125 135
126 } // namespace net 136 } // namespace net
OLDNEW
« no previous file with comments | « net/base/backoff_entry.h ('k') | net/base/backoff_entry_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698