Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
nghttp2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
nghttp2
Commits
727ba490
Commit
727ba490
authored
Aug 18, 2015
by
Nora
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
h2load adding timeout options
parent
71623b67
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
126 additions
and
9 deletions
+126
-9
doc/h2load.h2r
doc/h2load.h2r
+3
-0
src/h2load.cc
src/h2load.cc
+112
-9
src/h2load.h
src/h2load.h
+11
-0
No files found.
doc/h2load.h2r
View file @
727ba490
...
...
@@ -19,6 +19,9 @@ requests
This is the subset of the number reported in ``failed`` and most
likely the network level failures or stream was reset by
RST_STREAM.
timeout
The number of requests whose connection timed out before they
were completed.
status codes
The number of status code h2load received.
...
...
src/h2load.cc
View file @
727ba490
...
...
@@ -74,8 +74,9 @@ namespace h2load {
Config
::
Config
()
:
data_length
(
-
1
),
addrs
(
nullptr
),
nreqs
(
1
),
nclients
(
1
),
nthreads
(
1
),
max_concurrent_streams
(
-
1
),
window_bits
(
30
),
connection_window_bits
(
30
),
rate
(
0
),
nconns
(
0
),
no_tls_proto
(
PROTO_HTTP2
),
data_fd
(
-
1
),
port
(
0
),
default_port
(
0
),
verbose
(
false
)
{}
rate
(
0
),
nconns
(
0
),
conn_active_timeout
(
0
),
conn_inactivity_timeout
(
0
),
no_tls_proto
(
PROTO_HTTP2
),
data_fd
(
-
1
),
port
(
0
),
default_port
(
0
),
verbose
(
false
)
{}
Config
::~
Config
()
{
freeaddrinfo
(
addrs
);
...
...
@@ -118,14 +119,16 @@ RequestStat::RequestStat() : data_offset(0), completed(false) {}
Stats
::
Stats
(
size_t
req_todo
)
:
req_todo
(
0
),
req_started
(
0
),
req_done
(
0
),
req_success
(
0
),
req_status_success
(
0
),
req_failed
(
0
),
req_error
(
0
),
bytes_total
(
0
),
bytes_head
(
0
),
bytes_body
(
0
),
status
(),
req_stats
(
req_todo
)
{}
req_status_success
(
0
),
req_failed
(
0
),
req_error
(
0
),
req_timedout
(
0
),
bytes_total
(
0
),
bytes_head
(
0
),
bytes_body
(
0
),
status
(),
req_stats
(
req_todo
)
{}
Stream
::
Stream
()
:
status_success
(
-
1
)
{}
namespace
{
void
writecb
(
struct
ev_loop
*
loop
,
ev_io
*
w
,
int
revents
)
{
auto
client
=
static_cast
<
Client
*>
(
w
->
data
);
client
->
restart_timeout
();
auto
rv
=
client
->
do_write
();
if
(
rv
==
Client
::
ERR_CONNECT_FAIL
)
{
client
->
disconnect
();
...
...
@@ -145,6 +148,7 @@ void writecb(struct ev_loop *loop, ev_io *w, int revents) {
namespace
{
void
readcb
(
struct
ev_loop
*
loop
,
ev_io
*
w
,
int
revents
)
{
auto
client
=
static_cast
<
Client
*>
(
w
->
data
);
client
->
restart_timeout
();
if
(
client
->
do_read
()
!=
0
)
{
client
->
fail
();
return
;
...
...
@@ -178,6 +182,22 @@ void second_timeout_w_cb(struct ev_loop *loop, ev_timer *w, int revents) {
}
}
// namespace
namespace
{
// Called when an a connection has been inactive for a set period of time
// or a fixed amount of time after all requests have been made on a
// connection
void
conn_timeout_cb
(
EV_P_
ev_timer
*
w
,
int
revents
)
{
auto
client
=
static_cast
<
Client
*>
(
w
->
data
);
ev_timer_stop
(
client
->
worker
->
loop
,
&
client
->
conn_inactivity_watcher
);
ev_timer_stop
(
client
->
worker
->
loop
,
&
client
->
conn_active_watcher
);
if
(
util
::
check_socket_connected
(
client
->
fd
))
{
client
->
timeout
();
}
}
}
// namespace
Client
::
Client
(
Worker
*
worker
,
size_t
req_todo
)
:
worker
(
worker
),
ssl
(
nullptr
),
next_addr
(
config
.
addrs
),
reqidx
(
0
),
state
(
CLIENT_IDLE
),
first_byte_received
(
false
),
req_todo
(
req_todo
),
...
...
@@ -187,6 +207,14 @@ Client::Client(Worker *worker, size_t req_todo)
wev
.
data
=
this
;
rev
.
data
=
this
;
conn_inactivity_watcher
.
data
=
this
;
ev_init
(
&
conn_inactivity_watcher
,
conn_timeout_cb
);
conn_inactivity_watcher
.
repeat
=
worker
->
config
->
conn_inactivity_timeout
;
conn_active_watcher
.
data
=
this
;
ev_timer_init
(
&
conn_active_watcher
,
conn_timeout_cb
,
worker
->
config
->
conn_active_timeout
,
0
);
}
Client
::~
Client
()
{
disconnect
();
}
...
...
@@ -197,6 +225,10 @@ int Client::do_write() { return writefn(*this); }
int
Client
::
connect
()
{
record_start_time
(
&
worker
->
stats
);
if
(
worker
->
config
->
conn_inactivity_timeout
>
0
)
{
ev_timer_again
(
worker
->
loop
,
&
conn_inactivity_watcher
);
}
while
(
next_addr
)
{
auto
addr
=
next_addr
;
next_addr
=
next_addr
->
ai_next
;
...
...
@@ -244,6 +276,18 @@ int Client::connect() {
return
0
;
}
void
Client
::
timeout
()
{
process_timedout_streams
();
disconnect
();
}
void
Client
::
restart_timeout
()
{
if
(
worker
->
config
->
conn_inactivity_timeout
>
0
)
{
ev_timer_again
(
worker
->
loop
,
&
conn_inactivity_watcher
);
}
}
void
Client
::
fail
()
{
process_abandoned_streams
();
...
...
@@ -251,6 +295,9 @@ void Client::fail() {
}
void
Client
::
disconnect
()
{
ev_timer_stop
(
worker
->
loop
,
&
conn_inactivity_watcher
);
ev_timer_stop
(
worker
->
loop
,
&
conn_active_watcher
);
streams
.
clear
();
session
.
reset
();
state
=
CLIENT_IDLE
;
...
...
@@ -274,6 +321,25 @@ void Client::submit_request() {
auto
req_stat
=
&
worker
->
stats
.
req_stats
[
worker
->
stats
.
req_started
++
];
session
->
submit_request
(
req_stat
);
++
req_started
;
// if an active timeout is set and this is the last request to be submitted
// on this connection, start the active timeout.
if
(
worker
->
config
->
conn_active_timeout
>
0
&&
req_started
>=
req_todo
)
{
ev_timer_start
(
worker
->
loop
,
&
conn_active_watcher
);
}
}
void
Client
::
process_timedout_streams
()
{
for
(
auto
&
req_stat
:
worker
->
stats
.
req_stats
)
{
if
(
!
req_stat
.
completed
)
{
req_stat
.
stream_close_time
=
std
::
chrono
::
steady_clock
::
now
();
}
}
auto
req_timed_out
=
req_todo
-
req_done
;
worker
->
stats
.
req_timedout
+=
req_timed_out
;
process_abandoned_streams
();
}
void
Client
::
process_abandoned_streams
()
{
...
...
@@ -1078,7 +1144,8 @@ Options:
Available protocol: )"
;
#endif // !HAVE_SPDYLAY
out
<<
NGHTTP2_CLEARTEXT_PROTO_VERSION_ID
<<
R"(
Default: )"
<<
NGHTTP2_CLEARTEXT_PROTO_VERSION_ID
<<
R"(
Default: )"
<<
NGHTTP2_CLEARTEXT_PROTO_VERSION_ID
<<
R"(
-d, --data=<PATH>
Post FILE to server. The request method is changed to
POST.
...
...
@@ -1100,10 +1167,26 @@ Options:
to make the -n requests specified. The default value
for this option is 0. The -n option is not required if
the -C option is being used.
-T, --connection-active-timeout=<N>
Specifies the maximum time that h2load is willing to
keep a connection open, regardless of the activity on
said connection. <N> must be a positive integer,
specifying the number of seconds to wait. When no
timeout value is set (either active or inactive), h2load
will keep a connection open indefinitely, waiting for a
response.
-N, --connection-inactivity-timeout=<N>
Specifies the amount of time that h2load is willing to
wait to see activity on a given connection. <N> must be
a positive integer, specifying the number of seconds to
wait. When no timeout value is set (either active or
inactive), h2load will keep a connection open
indefinitely, waiting for a response.
-v, --verbose
Output debug information.
--version Display version information and exit.
-h, --help Display this help and exit.)"
<<
std
::
endl
;
-h, --help Display this help and exit.)"
<<
std
::
endl
;
}
}
// namespace
...
...
@@ -1137,10 +1220,12 @@ int main(int argc, char **argv) {
{
"ciphers"
,
required_argument
,
&
flag
,
2
},
{
"rate"
,
required_argument
,
nullptr
,
'r'
},
{
"num-conns"
,
required_argument
,
nullptr
,
'C'
},
{
"connection-active-timeout"
,
required_argument
,
nullptr
,
'T'
},
{
"connection-inactivity-timeout"
,
required_argument
,
nullptr
,
'N'
},
{
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:C:
"
,
long_options
,
&
option_index
);
auto
c
=
getopt_long
(
argc
,
argv
,
"hvW:c:d:m:n:p:t:w:H:i:r:C:
T:N:"
,
long_options
,
&
option_index
);
if
(
c
==
-
1
)
{
break
;
}
...
...
@@ -1251,6 +1336,22 @@ int main(int argc, char **argv) {
exit
(
EXIT_FAILURE
);
}
break
;
case
'T'
:
config
.
conn_active_timeout
=
strtoul
(
optarg
,
nullptr
,
10
);
if
(
config
.
conn_active_timeout
<=
0
)
{
std
::
cerr
<<
"-T: the conn_active_timeout wait time "
<<
"must be positive."
<<
std
::
endl
;
exit
(
EXIT_FAILURE
);
}
break
;
case
'N'
:
config
.
conn_inactivity_timeout
=
strtoul
(
optarg
,
nullptr
,
10
);
if
(
config
.
conn_inactivity_timeout
<=
0
)
{
std
::
cerr
<<
"-N: the conn_inactivity_timeout wait time "
<<
"must be positive."
<<
std
::
endl
;
exit
(
EXIT_FAILURE
);
}
break
;
case
'v'
:
config
.
verbose
=
true
;
break
;
...
...
@@ -1656,6 +1757,7 @@ int main(int argc, char **argv) {
stats
.
req_todo
+=
s
.
req_todo
;
stats
.
req_started
+=
s
.
req_started
;
stats
.
req_done
+=
s
.
req_done
;
stats
.
req_timedout
+=
s
.
req_timedout
;
stats
.
req_success
+=
s
.
req_success
;
stats
.
req_status_success
+=
s
.
req_status_success
;
stats
.
req_failed
+=
s
.
req_failed
;
...
...
@@ -1697,7 +1799,8 @@ finished in )" << util::format_duration(duration) << ", " << rps << " req/s, "
requests: )"
<<
stats
.
req_todo
<<
" total, "
<<
stats
.
req_started
<<
" started, "
<<
stats
.
req_done
<<
" done, "
<<
stats
.
req_status_success
<<
" succeeded, "
<<
stats
.
req_failed
<<
" failed, "
<<
stats
.
req_error
<<
R"( errored
<<
" failed, "
<<
stats
.
req_error
<<
" errored, "
<<
stats
.
req_timedout
<<
R"( timeout
status codes: )"
<<
stats
.
status
[
2
]
<<
" 2xx, "
<<
stats
.
status
[
3
]
<<
" 3xx, "
<<
stats
.
status
[
4
]
<<
" 4xx, "
<<
stats
.
status
[
5
]
<<
R"( 5xx
traffic: )"
<<
stats
.
bytes_total
<<
" bytes total, "
<<
stats
.
bytes_head
...
...
src/h2load.h
View file @
727ba490
...
...
@@ -81,6 +81,10 @@ struct Config {
size_t
rate
;
// number of connections made
size_t
nconns
;
// amount of time to wait for activity on a given connection
ssize_t
conn_active_timeout
;
// amount of time to wait after the last request is made on a connection
ssize_t
conn_inactivity_timeout
;
enum
{
PROTO_HTTP2
,
PROTO_SPDY2
,
PROTO_SPDY3
,
PROTO_SPDY3_1
}
no_tls_proto
;
// file descriptor for upload data
int
data_fd
;
...
...
@@ -144,6 +148,8 @@ struct Stats {
// The number of requests failed due to network errors. This is
// subset of req_failed.
size_t
req_error
;
// The number of requests that failed due to timeout.
size_t
req_timedout
;
// The number of bytes received on the "wire". If SSL/TLS is used,
// this is the number of decrypted bytes the application received.
int64_t
bytes_total
;
...
...
@@ -214,6 +220,8 @@ struct Client {
size_t
req_done
;
int
fd
;
Buffer
<
64
_k
>
wb
;
ev_timer
conn_active_watcher
;
ev_timer
conn_inactivity_watcher
;
enum
{
ERR_CONNECT_FAIL
=
-
100
};
...
...
@@ -222,7 +230,10 @@ struct Client {
int
connect
();
void
disconnect
();
void
fail
();
void
timeout
();
void
restart_timeout
();
void
submit_request
();
void
process_timedout_streams
();
void
process_abandoned_streams
();
void
report_progress
();
void
report_tls_info
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment