forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
drain_manager_impl.cc
72 lines (58 loc) · 2.54 KB
/
drain_manager_impl.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "server/drain_manager_impl.h"
#include <chrono>
#include <cstdint>
#include <functional>
#include "envoy/event/dispatcher.h"
#include "envoy/event/timer.h"
#include "envoy/runtime/runtime.h"
#include "envoy/server/instance.h"
#include "common/common/assert.h"
namespace Envoy {
namespace Server {
DrainManagerImpl::DrainManagerImpl(Instance& server, envoy::api::v2::Listener::DrainType drain_type)
: server_(server), drain_type_(drain_type) {}
bool DrainManagerImpl::drainClose() const {
// If we are actively HC failed and the drain type is default, always drain close.
//
// TODO(mattklein123): In relation to x-envoy-immediate-health-check-fail, it would be better
// if even in the case of server health check failure we had some period of drain ramp up. This
// would allow the other side to fail health check for the host which will require some thread
// jumps versus immediately start GOAWAY/connection thrashing.
if (drain_type_ == envoy::api::v2::Listener_DrainType_DEFAULT && server_.healthCheckFailed()) {
return true;
}
if (!draining()) {
return false;
}
// We use the tick time as in increasing chance that we shutdown connections.
return static_cast<uint64_t>(drain_time_completed_.load()) >
(server_.random().random() % server_.options().drainTime().count());
}
void DrainManagerImpl::drainSequenceTick() {
ENVOY_LOG(trace, "drain tick #{}", drain_time_completed_.load());
ASSERT(drain_time_completed_.load() < server_.options().drainTime().count());
++drain_time_completed_;
if (drain_time_completed_.load() < server_.options().drainTime().count()) {
drain_tick_timer_->enableTimer(std::chrono::milliseconds(1000));
} else if (drain_sequence_completion_) {
drain_sequence_completion_();
}
}
void DrainManagerImpl::startDrainSequence(std::function<void()> completion) {
drain_sequence_completion_ = completion;
ASSERT(!drain_tick_timer_);
drain_tick_timer_ = server_.dispatcher().createTimer([this]() -> void { drainSequenceTick(); });
drainSequenceTick();
}
void DrainManagerImpl::startParentShutdownSequence() {
ASSERT(!parent_shutdown_timer_);
parent_shutdown_timer_ = server_.dispatcher().createTimer([this]() -> void {
// Shut down the parent now. It should have already been draining.
ENVOY_LOG(info, "shutting down parent after drain");
server_.hotRestart().terminateParent();
});
parent_shutdown_timer_->enableTimer(std::chrono::duration_cast<std::chrono::milliseconds>(
server_.options().parentShutdownTime()));
}
} // namespace Server
} // namespace Envoy