@@ -18,6 +18,9 @@ pub(super) struct BalanceCapacity {
18
18
handler : Option < Box < dyn Handler > > ,
19
19
capacity : usize ,
20
20
in_flight_requests : AtomicUsize ,
21
+ log_at_percentage : usize ,
22
+ throttle_at_percentage : usize ,
23
+ dl_only_at_percentage : usize ,
21
24
}
22
25
23
26
impl BalanceCapacity {
@@ -26,6 +29,9 @@ impl BalanceCapacity {
26
29
handler : None ,
27
30
capacity,
28
31
in_flight_requests : AtomicUsize :: new ( 0 ) ,
32
+ log_at_percentage : read_env_percentage ( "WEB_CAPACITY_LOG_PCT" , 20 ) ,
33
+ throttle_at_percentage : read_env_percentage ( "WEB_CAPACITY_THROTTLE_PCT" , 70 ) ,
34
+ dl_only_at_percentage : read_env_percentage ( "WEB_CAPACITY_DL_ONLY_PCT" , 80 ) ,
29
35
}
30
36
}
31
37
}
@@ -43,8 +49,8 @@ impl Handler for BalanceCapacity {
43
49
let handler = self . handler . as_ref ( ) . unwrap ( ) ;
44
50
let load = 100 * count / self . capacity ;
45
51
46
- // Begin logging request count at 20% capacity
47
- if load >= 20 {
52
+ // Begin logging request count so early stages of load increase can be located
53
+ if load >= self . log_at_percentage {
48
54
super :: log_request:: add_custom_metadata ( request, "in_flight_requests" , count) ;
49
55
}
50
56
@@ -53,23 +59,24 @@ impl Handler for BalanceCapacity {
53
59
return handler. call ( request) ;
54
60
}
55
61
56
- // Reject read-only requests after reaching 70% load . Bots are likely to send only safe
62
+ // Reject read-only requests as load nears capacity . Bots are likely to send only safe
57
63
// requests and this helps prioritize requests that users may be reluctant to retry.
58
- if load >= 70 && request. method ( ) . is_safe ( ) {
59
- return over_capcity_response ( ) ;
64
+ if load >= self . throttle_at_percentage && request. method ( ) . is_safe ( ) {
65
+ return over_capacity_response ( request ) ;
60
66
}
61
67
62
- // At 80% load, all non-download requests are rejected
63
- if load >= 80 {
64
- return over_capcity_response ( ) ;
68
+ // As load reaches capacity , all non-download requests are rejected
69
+ if load >= self . dl_only_at_percentage {
70
+ return over_capacity_response ( request ) ;
65
71
}
66
72
67
73
handler. call ( request)
68
74
}
69
75
}
70
76
71
- fn over_capcity_response ( ) -> AfterResult {
77
+ fn over_capacity_response ( request : & mut dyn RequestExt ) -> AfterResult {
72
78
// TODO: Generate an alert so we can investigate
79
+ super :: log_request:: add_custom_metadata ( request, "cause" , "over capacity" ) ;
73
80
let body = "Service temporarily unavailable" ;
74
81
Response :: builder ( )
75
82
. status ( StatusCode :: SERVICE_UNAVAILABLE )
@@ -78,6 +85,14 @@ fn over_capcity_response() -> AfterResult {
78
85
. map_err ( box_error)
79
86
}
80
87
88
+ fn read_env_percentage ( name : & str , default : usize ) -> usize {
89
+ if let Ok ( value) = std:: env:: var ( name) {
90
+ value. parse ( ) . unwrap_or ( default)
91
+ } else {
92
+ default
93
+ }
94
+ }
95
+
81
96
// FIXME(JTG): I've copied the following from my `conduit-hyper` crate. Once we transition from
82
97
// `civet`, we could pass the in_flight_request count from `condut-hyper` via a request extension.
83
98
0 commit comments