add support for requests until reconnect via -q
This commit is contained in:
parent
9e6c0685a2
commit
b3564ba872
|
@ -98,6 +98,7 @@ Config::Config()
|
|||
verbose(false),
|
||||
timing_script(false),
|
||||
base_uri_unix(false),
|
||||
requests_until_reconnect(0),
|
||||
unix_addr{},
|
||||
rps(0.) {}
|
||||
|
||||
|
@ -215,7 +216,7 @@ void rate_period_timeout_w_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
|||
--worker->nreqs_rem;
|
||||
}
|
||||
auto client =
|
||||
std::make_unique<Client>(worker->next_client_id++, worker, req_todo);
|
||||
std::make_unique<Client>(worker->next_client_id++, worker, req_todo, 0);
|
||||
|
||||
++worker->nconns_made;
|
||||
|
||||
|
@ -404,7 +405,8 @@ void client_request_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
Client::Client(uint32_t id, Worker *worker, size_t req_todo)
|
||||
Client::Client(uint32_t id, Worker *worker, size_t req_todo, uint32_t
|
||||
requests_until_reconnect)
|
||||
: wb(&worker->mcpool),
|
||||
cstat{},
|
||||
worker(worker),
|
||||
|
@ -418,6 +420,8 @@ Client::Client(uint32_t id, Worker *worker, size_t req_todo)
|
|||
req_inflight(0),
|
||||
req_started(0),
|
||||
req_done(0),
|
||||
req_until_reconnect(requests_until_reconnect),
|
||||
req_until_reconnect_rearmed(false),
|
||||
id(id),
|
||||
fd(-1),
|
||||
new_connection_requested(false),
|
||||
|
@ -573,12 +577,16 @@ int Client::try_again_or_fail() {
|
|||
if (req_left) {
|
||||
|
||||
if (worker->current_phase == Phase::MAIN_DURATION) {
|
||||
// At the moment, we don't have a facility to re-start request
|
||||
// already in in-flight. Make them fail.
|
||||
worker->stats.req_failed += req_inflight;
|
||||
worker->stats.req_error += req_inflight;
|
||||
if (req_inflight > 0) {
|
||||
// At the moment, we don't have a facility to re-start request
|
||||
// already in in-flight. Make them fail.
|
||||
worker->stats.req_failed += req_inflight;
|
||||
worker->stats.req_error += req_inflight;
|
||||
|
||||
req_inflight = 0;
|
||||
req_inflight = 0;
|
||||
} else {
|
||||
req_until_reconnect_rearmed = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep using current address
|
||||
|
@ -1343,7 +1351,7 @@ int get_ev_loop_flags() {
|
|||
} // namespace
|
||||
|
||||
Worker::Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t req_todo, size_t nclients,
|
||||
size_t rate, size_t max_samples, Config *config)
|
||||
uint32_t requests_until_reconnect, size_t rate, size_t max_samples, Config *config)
|
||||
: stats(req_todo, nclients),
|
||||
loop(ev_loop_new(get_ev_loop_flags())),
|
||||
ssl_ctx(ssl_ctx),
|
||||
|
@ -1355,6 +1363,7 @@ Worker::Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t req_todo, size_t nclients,
|
|||
nclients(nclients),
|
||||
nreqs_per_client(req_todo / nclients),
|
||||
nreqs_rem(req_todo % nclients),
|
||||
requests_until_reconnect(requests_until_reconnect),
|
||||
rate(rate),
|
||||
max_samples(max_samples),
|
||||
next_client_id(0) {
|
||||
|
@ -1430,7 +1439,8 @@ void Worker::run() {
|
|||
--nreqs_rem;
|
||||
}
|
||||
|
||||
auto client = std::make_unique<Client>(next_client_id++, this, req_todo);
|
||||
auto client = std::make_unique<Client>(next_client_id++, this, req_todo,
|
||||
requests_until_reconnect);
|
||||
if (client->connect() != 0) {
|
||||
std::cerr << "client could not connect to host" << std::endl;
|
||||
client->fail();
|
||||
|
@ -1837,14 +1847,20 @@ std::unique_ptr<Worker> create_worker(uint32_t id, SSL_CTX *ssl_ctx,
|
|||
<< " total requests" << std::endl;
|
||||
}
|
||||
|
||||
if (config.requests_until_reconnect > 0) {
|
||||
std::cout << " number of requests until reconnect: " <<
|
||||
config.requests_until_reconnect << std::endl;
|
||||
}
|
||||
|
||||
if (config.is_rate_mode()) {
|
||||
return std::make_unique<Worker>(id, ssl_ctx, nreqs, nclients, rate,
|
||||
max_samples, &config);
|
||||
return std::make_unique<Worker>(id, ssl_ctx, nreqs, nclients,
|
||||
config.requests_until_reconnect, rate, max_samples, &config);
|
||||
} else {
|
||||
// Here rate is same as client because the rate_timeout callback
|
||||
// will be called only once
|
||||
return std::make_unique<Worker>(id, ssl_ctx, nreqs, nclients, nclients,
|
||||
max_samples, &config);
|
||||
return std::make_unique<Worker>(id, ssl_ctx, nreqs, nclients,
|
||||
config.requests_until_reconnect,
|
||||
nclients, max_samples, &config);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
@ -1921,6 +1937,10 @@ Options:
|
|||
Number of native threads.
|
||||
Default: )"
|
||||
<< config.nthreads << R"(
|
||||
-q, --requests-until-reconnect=<N>
|
||||
Number of requests to issue per client before a reconnect is
|
||||
done from that client. Default is 0, which means this behavior
|
||||
is disabled.
|
||||
-i, --input-file=<PATH>
|
||||
Path of a file with multiple URIs are separated by EOLs.
|
||||
This option will disable URIs getting from command-line.
|
||||
|
@ -2130,10 +2150,11 @@ int main(int argc, char **argv) {
|
|||
{"log-file", required_argument, &flag, 10},
|
||||
{"connect-to", required_argument, &flag, 11},
|
||||
{"rps", required_argument, &flag, 12},
|
||||
{"requests-until-reconnect", required_argument, nullptr, 'q'},
|
||||
{nullptr, 0, nullptr, 0}};
|
||||
int option_index = 0;
|
||||
auto c = getopt_long(argc, argv,
|
||||
"hvW:c:d:m:n:p:t:w:H:i:r:T:N:D:B:", long_options,
|
||||
"hvW:c:d:m:n:p:t:w:H:i:r:T:N:D:B:q:", long_options,
|
||||
&option_index);
|
||||
if (c == -1) {
|
||||
break;
|
||||
|
@ -2143,6 +2164,9 @@ int main(int argc, char **argv) {
|
|||
config.nreqs = strtoul(optarg, nullptr, 10);
|
||||
nreqs_set_manually = true;
|
||||
break;
|
||||
case 'q':
|
||||
config.requests_until_reconnect = strtoul(optarg, nullptr, 10);
|
||||
break;
|
||||
case 'c':
|
||||
config.nclients = strtoul(optarg, nullptr, 10);
|
||||
break;
|
||||
|
|
12
src/h2load.h
12
src/h2load.h
|
@ -104,6 +104,7 @@ struct Config {
|
|||
uint16_t default_port;
|
||||
uint16_t connect_to_port;
|
||||
bool verbose;
|
||||
uint32_t requests_until_reconnect;
|
||||
bool timing_script;
|
||||
std::string base_uri;
|
||||
// true if UNIX domain socket is used. In this case, base_uri is
|
||||
|
@ -268,6 +269,9 @@ struct Worker {
|
|||
ev_timer timeout_watcher;
|
||||
// The next client ID this worker assigns
|
||||
uint32_t next_client_id;
|
||||
// the number of requests that should be processed before the client
|
||||
// reconnects
|
||||
const uint32_t requests_until_reconnect;
|
||||
// Keeps track of the current phase (for timing-based experiment) for the
|
||||
// worker
|
||||
Phase current_phase;
|
||||
|
@ -279,7 +283,7 @@ struct Worker {
|
|||
ev_timer warmup_watcher;
|
||||
|
||||
Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t nreq_todo, size_t nclients,
|
||||
size_t rate, size_t max_samples, Config *config);
|
||||
uint32_t reqs_until_reconnect, size_t rate, size_t max_samples, Config *config);
|
||||
~Worker();
|
||||
Worker(Worker &&o) = default;
|
||||
void run();
|
||||
|
@ -329,6 +333,8 @@ struct Client {
|
|||
size_t req_started;
|
||||
// The number of requests this client has done so far.
|
||||
size_t req_done;
|
||||
// The number of requests this client has left until a reconnect is done.
|
||||
uint32_t req_until_reconnect;
|
||||
// The client id per worker
|
||||
uint32_t id;
|
||||
int fd;
|
||||
|
@ -336,6 +342,7 @@ struct Client {
|
|||
ev_timer conn_inactivity_watcher;
|
||||
std::string selected_proto;
|
||||
bool new_connection_requested;
|
||||
bool req_until_reconnect_rearmed;
|
||||
// true if the current connection will be closed, and no more new
|
||||
// request cannot be processed.
|
||||
bool final;
|
||||
|
@ -356,7 +363,8 @@ struct Client {
|
|||
|
||||
enum { ERR_CONNECT_FAIL = -100 };
|
||||
|
||||
Client(uint32_t id, Worker *worker, size_t req_todo);
|
||||
Client(uint32_t id, Worker *worker, size_t req_todo, uint32_t
|
||||
requests_until_reconnect);
|
||||
~Client();
|
||||
int make_socket(addrinfo *addr);
|
||||
int connect();
|
||||
|
|
|
@ -89,18 +89,25 @@ int htp_msg_completecb(llhttp_t *htp) {
|
|||
|
||||
session->stream_resp_counter_ += 2;
|
||||
|
||||
if (client->final) {
|
||||
if (client->final || (client->worker->requests_until_reconnect > 0 &&
|
||||
client->req_until_reconnect == 0)) {
|
||||
session->stream_req_counter_ = session->stream_resp_counter_;
|
||||
|
||||
// Connection is going down. If we have still request to do,
|
||||
// create new connection and keep on doing the job.
|
||||
if (client->req_left) {
|
||||
client->req_until_reconnect = client->worker->requests_until_reconnect;
|
||||
client->req_until_reconnect_rearmed = true;
|
||||
client->try_new_connection();
|
||||
}
|
||||
|
||||
return HPE_PAUSED;
|
||||
}
|
||||
|
||||
if (client->worker->requests_until_reconnect > 0) {
|
||||
client->req_until_reconnect--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
|
Loading…
Reference in New Issue