-
Notifications
You must be signed in to change notification settings - Fork 83
/
Copy pathbenchmark_client_impl.h
186 lines (166 loc) · 8.48 KB
/
benchmark_client_impl.h
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#pragma once
#include "envoy/api/api.h"
#include "envoy/event/dispatcher.h"
#include "envoy/http/conn_pool.h"
#include "envoy/network/address.h"
#include "envoy/runtime/runtime.h"
#include "envoy/stats/scope.h"
#include "envoy/stats/store.h"
#include "envoy/upstream/upstream.h"
#include "nighthawk/client/benchmark_client.h"
#include "nighthawk/common/request_source.h"
#include "nighthawk/common/sequencer.h"
#include "nighthawk/common/statistic.h"
#include "nighthawk/user_defined_output/user_defined_output_plugin.h"
#include "external/envoy/source/common/common/logger.h"
#include "external/envoy/source/common/common/random_generator.h"
#include "external/envoy/source/common/http/http1/conn_pool.h"
#include "external/envoy/source/common/http/http2/conn_pool.h"
#include "external/envoy/source/common/runtime/runtime_impl.h"
#include "api/client/options.pb.h"
#include "source/client/stream_decoder.h"
#include "source/common/statistic_impl.h"
namespace Nighthawk {
namespace Client {
using namespace std::chrono_literals;
#define ALL_BENCHMARK_CLIENT_COUNTERS(COUNTER) \
COUNTER(stream_resets) \
COUNTER(http_1xx) \
COUNTER(http_2xx) \
COUNTER(http_3xx) \
COUNTER(http_4xx) \
COUNTER(http_5xx) \
COUNTER(http_xxx) \
COUNTER(pool_overflow) \
COUNTER(pool_connection_failure) \
COUNTER(user_defined_plugin_handle_headers_failure) \
COUNTER(user_defined_plugin_handle_data_failure)
// For counter metrics, Nighthawk use Envoy Counter directly. For histogram metrics, Nighthawk uses
// its own Statistic instead of Envoy Histogram. Here BenchmarkClientCounters contains only counters
// while BenchmarkClientStatistic contains only histograms.
struct BenchmarkClientCounters {
ALL_BENCHMARK_CLIENT_COUNTERS(GENERATE_COUNTER_STRUCT)
};
// BenchmarkClientStatistic contains only histogram metrics.
struct BenchmarkClientStatistic {
BenchmarkClientStatistic(BenchmarkClientStatistic&& statistic) noexcept;
BenchmarkClientStatistic(StatisticPtr&& connect_stat, StatisticPtr&& response_stat,
StatisticPtr&& response_header_size_stat,
StatisticPtr&& response_body_size_stat, StatisticPtr&& latency_1xx_stat,
StatisticPtr&& latency_2xx_stat, StatisticPtr&& latency_3xx_stat,
StatisticPtr&& latency_4xx_stat, StatisticPtr&& latency_5xx_stat,
StatisticPtr&& latency_xxx_stat,
StatisticPtr&& origin_latency_statistic);
// These are declared order dependent. Changing ordering may trigger on assert upon
// destruction when tls has been involved during usage.
StatisticPtr connect_statistic;
StatisticPtr response_statistic;
StatisticPtr response_header_size_statistic;
StatisticPtr response_body_size_statistic;
StatisticPtr latency_1xx_statistic;
StatisticPtr latency_2xx_statistic;
StatisticPtr latency_3xx_statistic;
StatisticPtr latency_4xx_statistic;
StatisticPtr latency_5xx_statistic;
StatisticPtr latency_xxx_statistic;
StatisticPtr origin_latency_statistic;
};
class Http1PoolImpl : public Envoy::Http::FixedHttpConnPoolImpl {
public:
enum class ConnectionReuseStrategy {
MRU,
LRU,
};
using Envoy::Http::FixedHttpConnPoolImpl::FixedHttpConnPoolImpl;
Envoy::Http::ConnectionPool::Cancellable*
newStream(Envoy::Http::ResponseDecoder& response_decoder,
Envoy::Http::ConnectionPool::Callbacks& callbacks,
const Instance::StreamOptions& options) override;
void setConnectionReuseStrategy(const ConnectionReuseStrategy connection_reuse_strategy) {
connection_reuse_strategy_ = connection_reuse_strategy;
}
void setPrefetchConnections(const bool prefetch_connections) {
prefetch_connections_ = prefetch_connections;
}
private:
ConnectionReuseStrategy connection_reuse_strategy_{};
bool prefetch_connections_{};
};
class BenchmarkClientHttpImpl : public BenchmarkClient,
public StreamDecoderCompletionCallback,
public Envoy::Logger::Loggable<Envoy::Logger::Id::main> {
public:
BenchmarkClientHttpImpl(Envoy::Api::Api& api, Envoy::Event::Dispatcher& dispatcher,
Envoy::Stats::Scope& scope, BenchmarkClientStatistic& statistic,
Envoy::Http::Protocol protocol,
Envoy::Upstream::ClusterManagerPtr& cluster_manager,
Envoy::Tracing::TracerSharedPtr& tracer, absl::string_view cluster_name,
RequestGenerator request_generator,
const bool provide_resource_backpressure,
absl::string_view latency_response_header_name,
std::vector<UserDefinedOutputNamePluginPair> user_defined_output_plugins);
void setConnectionLimit(uint32_t connection_limit) { connection_limit_ = connection_limit; }
void setMaxPendingRequests(uint32_t max_pending_requests) {
max_pending_requests_ = max_pending_requests;
}
void setMaxActiveRequests(uint32_t max_active_requests) {
max_active_requests_ = max_active_requests;
}
void setMaxRequestsPerConnection(uint32_t max_requests_per_connection) {
max_requests_per_connection_ = max_requests_per_connection;
}
// BenchmarkClient
void terminate() override;
StatisticPtrMap statistics() const override;
bool shouldMeasureLatencies() const override { return measure_latencies_; }
void setShouldMeasureLatencies(bool measure_latencies) override {
measure_latencies_ = measure_latencies;
}
bool tryStartRequest(CompletionCallback caller_completion_callback) override;
Envoy::Stats::Scope& scope() const override { return *scope_; }
/**
* Returns additional output from any specified User Defined Output plugins.
*/
std::vector<nighthawk::client::UserDefinedOutput> getUserDefinedOutputResults() const override;
// StreamDecoderCompletionCallback
void onComplete(bool success, const Envoy::Http::ResponseHeaderMap& headers) override;
void onPoolFailure(Envoy::Http::ConnectionPool::PoolFailureReason reason) override;
void exportLatency(const uint32_t response_code, const uint64_t latency_ns) override;
void handleResponseData(const Envoy::Buffer::Instance& response_data) override;
// Helpers
absl::optional<::Envoy::Upstream::HttpPoolData> pool() {
const auto thread_local_cluster = cluster_manager_->getThreadLocalCluster(cluster_name_);
Envoy::Upstream::HostConstSharedPtr host =
Envoy::Upstream::LoadBalancer::onlyAllowSynchronousHostSelection(
thread_local_cluster->chooseHost(nullptr));
return thread_local_cluster->httpConnPool(host, Envoy::Upstream::ResourcePriority::Default,
protocol_, nullptr);
}
private:
Envoy::Api::Api& api_;
Envoy::Event::Dispatcher& dispatcher_;
Envoy::Stats::ScopeSharedPtr scope_;
BenchmarkClientStatistic statistic_;
const Envoy::Http::Protocol protocol_;
std::chrono::seconds timeout_{5s};
uint32_t connection_limit_{1};
uint32_t max_pending_requests_{1};
uint32_t max_active_requests_{UINT32_MAX};
uint32_t max_requests_per_connection_{UINT32_MAX};
Envoy::Event::TimerPtr timer_;
Envoy::Random::RandomGeneratorImpl generator_;
uint64_t requests_completed_{};
uint64_t requests_initiated_{};
bool measure_latencies_{};
BenchmarkClientCounters benchmark_client_counters_;
Envoy::Upstream::ClusterManagerPtr& cluster_manager_;
Envoy::Tracing::TracerSharedPtr& tracer_;
std::string cluster_name_;
const RequestGenerator request_generator_;
const bool provide_resource_backpressure_;
const std::string latency_response_header_name_;
Envoy::Event::TimerPtr drain_timer_;
std::vector<UserDefinedOutputNamePluginPair> user_defined_output_plugins_;
};
} // namespace Client
} // namespace Nighthawk