forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathasync_round_robin_lb.cc
More file actions
101 lines (87 loc) · 4.2 KB
/
async_round_robin_lb.cc
File metadata and controls
101 lines (87 loc) · 4.2 KB
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "test/integration/async_round_robin_lb.h"
#include "source/common/router/router.h"
namespace Envoy {
namespace Upstream {
class AsyncRoundRobinLoadBalancer : public RoundRobinLoadBalancer {
public:
struct AsyncInfo : public AsyncHostSelectionHandle {
AsyncInfo(HostConstSharedPtr host, LoadBalancerContext* ctx)
: preselected_host_(host), context_(ctx), detachable_(std::make_shared<Detachable>(this)) {}
HostConstSharedPtr preselected_host_;
LoadBalancerContext* context_;
virtual void cancel() override { detachable_->parent_ = nullptr; }
// If cancel is called, parent will be nulled out.
struct Detachable {
Detachable(AsyncInfo* parent) : parent_(parent) {}
AsyncInfo* parent_;
};
std::shared_ptr<Detachable> detachable_;
};
AsyncRoundRobinLoadBalancer(
const PrioritySet& priority_set, const PrioritySet* local_priority_set, ClusterLbStats& stats,
Runtime::Loader& runtime, Random::RandomGenerator& random, uint32_t healthy_panic_threshold,
const envoy::extensions::load_balancing_policies::round_robin::v3::RoundRobin&
round_robin_config,
TimeSource& time_source, bool hang)
: RoundRobinLoadBalancer(priority_set, local_priority_set, stats, runtime, random,
healthy_panic_threshold, round_robin_config, time_source),
hang_(hang) {}
void onCallback() {
ENVOY_LOG_MISC(debug, "Finishing asynchronous host selection\n");
for (std::shared_ptr<AsyncInfo::Detachable>& handle : handles_) {
if (handle->parent_) {
handle->parent_->context_->onAsyncHostSelection(
std::move(handle->parent_->preselected_host_), "");
}
}
handles_.clear();
}
// When the caller requests a host, use the parent LB to select the host, but
// instead of returning it, schedule a callback to cede, and call onAsyncHostSelection at
// the end of the event loop.
HostSelectionResponse chooseHost(LoadBalancerContext* context) override {
// Do a really ugly dynamic cast to avoid plumbing the dispatcher through
// cleanly (see reverted PR https://github.com/envoyproxy/envoy/pull/38020)
// which was only needed for this test.
if (!callback_) {
Router::Filter* router = dynamic_cast<Router::Filter*>(context);
ASSERT(router != nullptr);
callback_ =
router->callbacks()->dispatcher().createSchedulableCallback([this]() { onCallback(); });
}
if (!hang_) {
ENVOY_LOG_MISC(debug, "Starting asynchronous host selection\n");
callback_->scheduleCallbackCurrentIteration();
} else {
ENVOY_LOG_MISC(debug, "Hanging asynchronous host selection\n");
}
std::unique_ptr<AsyncInfo> info =
std::make_unique<AsyncInfo>(RoundRobinLoadBalancer::chooseHost(context).host, context);
handles_.push_back(info->detachable_);
return {nullptr, std::move(info)};
}
private:
std::list<std::shared_ptr<AsyncInfo::Detachable>> handles_;
Event::SchedulableCallbackPtr callback_;
const bool hang_;
};
LoadBalancerPtr AsyncRoundRobinCreator::operator()(LoadBalancerParams params,
OptRef<const LoadBalancerConfig> lb_config,
const ClusterInfo& cluster_info,
const PrioritySet&, Runtime::Loader& runtime,
Random::RandomGenerator& random,
TimeSource& time_source) {
envoy::extensions::load_balancing_policies::round_robin::v3::RoundRobin config;
bool hang = dynamic_cast<const TypedAsyncRoundRobinLbConfig*>(lb_config.ptr())->lb_config_.hang();
return std::make_unique<AsyncRoundRobinLoadBalancer>(
params.priority_set, params.local_priority_set, cluster_info.lbStats(), runtime, random,
PROTOBUF_PERCENT_TO_ROUNDED_INTEGER_OR_DEFAULT(cluster_info.lbConfig(),
healthy_panic_threshold, 100, 50),
config, time_source, hang);
}
/**
* Static registration for the Factory. @see RegisterFactory.
*/
REGISTER_FACTORY(AsyncRoundRobinFactory, TypedLoadBalancerFactory);
} // namespace Upstream
} // namespace Envoy