らくがきちょう

なんとなく

h2load で HTTP/2.0 に対応した負荷試験を実施する

HTTP のベンチマークツールは幾つかありますが、h2load は nghttp2 という HTTP 2.0 ライブラリに付属してくるだけあって、HTTP 2.0 にも対応したベンチマークツールです。 今回は h2load を CentOS7 上にインストールし、基本的な使い方を試してみます。

Nghttp2 のインストール

Nghttp2 は以下のサイトで公開されています。 現時点の最新バージョンは 1.29.0 です。

Nghtp2 は CentOS7 標準のリポジトリには含まれていません。 IUS にも存在せず、EPEL 上には存在するのですが、バージョンが 1.21.1 と古いです…

# yum --enablerepo=ius info nghttp2
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.riken.jp
 * epel: ftp.riken.jp
 * extras: ftp.riken.jp
 * ius: mirrors.tongji.edu.cn
 * updates: ftp.riken.jp
Available Packages
Name        : nghttp2
Arch        : x86_64
Version     : 1.21.1
Release     : 1.el7
Size        : 520 k
Repo        : epel/x86_64
Summary     : Experimental HTTP/2 client, server and proxy
URL         : https://nghttp2.org/
License     : MIT
Description : This package contains the HTTP/2 client, server and proxy programs.

とりあえず、EPEL からインストールします。

yum -y install epel-release
yum -y install nghttp2

インストールされました。

# which h2load
/usr/bin/h2load

h2load を実行する

h2load でよく利用するオプションは以下のようです。

オプション 意味 指定可能な値
-n 総リクエスト数。 リクエスト数がこの値に到達するまで、リクエストし続ける 整数を指定
-c クライアント数。 並行して実行するクライアントの数 整数を指定
-m クライアント当たりの、最大ストリーム並列数 整数を指定
-p プロトコル。 通常は HTTP バージョンを自動調整するが、明示的に特定バージョン指定したい場合に利用する h2chttp/1.1

実際に h2load を試してみます。

最小限の使い方

最小限の使い方は h2load に URL を指定するだけです。

# h2load http://172.20.0.171
starting benchmark...
spawning thread #0: 1 total client(s). 1 total requests
Application protocol: h2c
progress: 100% done

finished in 1.01ms, 986.19 req/s, 305.30KB/s
requests: 1 total, 1 started, 1 done, 1 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 1 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 317B (317) total, 92B (92) headers (space savings 46.82%), 177B (177) data
                     min         max         mean         sd        +/- sd
time for request:      371us       371us       371us         0us   100.00%
time for connect:      386us       386us       386us         0us   100.00%
time to 1st byte:      797us       797us       797us         0us   100.00%
req/s           :    1156.67     1156.67     1156.67        0.00   100.00%

「10 クライアントを並行して生成し、合計 100 リクエストに到達するまで実行する」場合は以下のように指定します。

# h2load -c 10 -n 100 http://172.20.0.171
starting benchmark...
spawning thread #0: 10 total client(s). 100 total requests
Application protocol: h2c
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done

finished in 6.79ms, 14721.04 req/s, 3.07MB/s
requests: 100 total, 100 started, 100 done, 100 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 100 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 21.38KB (21890) total, 2.04KB (2090) headers (space savings 87.92%), 17.29KB (17700) data
                     min         max         mean         sd        +/- sd
time for request:      141us       985us       546us       153us    75.00%
time for connect:      266us       664us       438us       118us    60.00%
time to 1st byte:     1.04ms      1.74ms      1.40ms       267us    40.00%
req/s           :    1528.92     1687.63     1593.23       49.42    60.00%

合計リクエスト数がクライアント数を下回る… という指定は出来ません。

# h2load -c 100 -n 10 http://172.20.0.171
-n, -c: the number of requests must be greater than or equal to the clients.

明示的に「HTTP/2.0」や「HTTP/1.1」等のプロトコルバージョンを指定するには -p オプションを指定します。

# h2load -p http/1.1 http://172.20.0.171
starting benchmark...
spawning thread #0: 1 total client(s). 1 total requests
Application protocol: http/1.1
progress: 100% done

finished in 1.03ms, 972.76 req/s, 390.43KB/s
requests: 1 total, 1 started, 1 done, 1 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 1 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 411B (411) total, 183B (183) headers (space savings 0.00%), 177B (177) data
                     min         max         mean         sd        +/- sd
time for request:      388us       388us       388us         0us   100.00%
time for connect:      408us       408us       408us         0us   100.00%
time to 1st byte:      800us       800us       800us         0us   100.00%
req/s           :    1186.25     1186.25     1186.25        0.00   100.00%

参考

h2load のヘルプ表示

# h2load --help
Usage: h2load [OPTIONS]... [URI]...
benchmarking tool for HTTP/2 and SPDY server

  <URI>       Specify URI to access.   Multiple URIs can be specified.
              URIs are used  in this order for each  client.  All URIs
              are used, then  first URI is used and then  2nd URI, and
              so  on.  The  scheme, host  and port  in the  subsequent
              URIs, if present,  are ignored.  Those in  the first URI
              are used solely.  Definition of a base URI overrides all
              scheme, host or port values.
Options:
  -n, --requests=<N>
              Number of  requests across all  clients.  If it  is used
              with --timing-script-file option,  this option specifies
              the number of requests  each client performs rather than
              the number of requests across all clients.
              Default: 1
  -c, --clients=<N>
              Number  of concurrent  clients.   With  -r option,  this
              specifies the maximum number of connections to be made.
              Default: 1
  -t, --threads=<N>
              Number of native threads.
              Default: 1
  -i, --input-file=<PATH>
              Path of a file with multiple URIs are separated by EOLs.
              This option will disable URIs getting from command-line.
              If '-' is given as <PATH>, URIs will be read from stdin.
              URIs are used  in this order for each  client.  All URIs
              are used, then  first URI is used and then  2nd URI, and
              so  on.  The  scheme, host  and port  in the  subsequent
              URIs, if present,  are ignored.  Those in  the first URI
              are used solely.  Definition of a base URI overrides all
              scheme, host or port values.
  -m, --max-concurrent-streams=<N>
              Max  concurrent  streams  to issue  per  session.   When
              http/1.1  is used,  this  specifies the  number of  HTTP
              pipelining requests in-flight.
              Default: 1
  -w, --window-bits=<N>
              Sets the stream level initial window size to (2**<N>)-1.
              For SPDY, 2**<N> is used instead.
              Default: 30
  -W, --connection-window-bits=<N>
              Sets  the  connection  level   initial  window  size  to
              (2**<N>)-1.  For SPDY, if <N>  is strictly less than 16,
              this option  is ignored.   Otherwise 2**<N> is  used for
              SPDY.
              Default: 30
  -H, --header=<HEADER>
              Add/Override a header to the requests.
  --ciphers=<SUITE>
              Set allowed  cipher list.  The  format of the  string is
              described in OpenSSL ciphers(1).
              Default: ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
  -p, --no-tls-proto=<PROTOID>
              Specify ALPN identifier of the  protocol to be used when
              accessing http URI without SSL/TLS.
              Available protocols: h2c and
              http/1.1
              Default: h2c
  -d, --data=<PATH>
              Post FILE to  server.  The request method  is changed to
              POST.   For  http/1.1 connection,  if  -d  is used,  the
              maximum number of in-flight pipelined requests is set to
              1.
  -r, --rate=<N>
              Specifies  the  fixed  rate  at  which  connections  are
              created.   The   rate  must   be  a   positive  integer,
              representing the  number of  connections to be  made per
              rate period.   The maximum  number of connections  to be
              made  is  given  in  -c   option.   This  rate  will  be
              distributed among  threads as  evenly as  possible.  For
              example,  with   -t2  and   -r4,  each  thread   gets  2
              connections per period.  When the rate is 0, the program
              will run  as it  normally does, creating  connections at
              whatever variable rate it  wants.  The default value for
              this option is 0.
  --rate-period=<DURATION>
              Specifies the time  period between creating connections.
              The period  must be a positive  number, representing the
              length of the period in time.  This option is ignored if
              the rate option is not used.  The default value for this
              option is 1s.
  -T, --connection-active-timeout=<DURATION>
              Specifies  the maximum  time that  h2load is  willing to
              keep a  connection open,  regardless of the  activity on
              said connection.  <DURATION> must be a positive integer,
              specifying the amount of time  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=<DURATION>
              Specifies the amount  of time that h2load  is willing to
              wait to see activity  on a given connection.  <DURATION>
              must  be a  positive integer,  specifying the  amount of
              time  to wait.   When no  timeout value  is set  (either
              active or inactive), h2load  will keep a connection open
              indefinitely, waiting for a response.
  --timing-script-file=<PATH>
              Path of a file containing one or more lines separated by
              EOLs.  Each script line is composed of two tab-separated
              fields.  The first field represents the time offset from
              the start of execution, expressed as a positive value of
              milliseconds  with microsecond  resolution.  The  second
              field represents the URI.  This option will disable URIs
              getting from  command-line.  If '-' is  given as <PATH>,
              script lines will be read  from stdin.  Script lines are
              used in order for each client.   If -n is given, it must
              be less  than or  equal to the  number of  script lines,
              larger values are clamped to the number of script lines.
              If -n is not given,  the number of requests will default
              to the  number of  script lines.   The scheme,  host and
              port defined in  the first URI are  used solely.  Values
              contained  in  other  URIs,  if  present,  are  ignored.
              Definition of a  base URI overrides all  scheme, host or
              port values.
  -B, --base-uri=(<URI>|unix:<PATH>)
              Specify URI from which the scheme, host and port will be
              used  for  all requests.   The  base  URI overrides  all
              values  defined either  at  the command  line or  inside
              input files.  If argument  starts with "unix:", then the
              rest  of the  argument will  be treated  as UNIX  domain
              socket path.   The connection is made  through that path
              instead of TCP.   In this case, scheme  is inferred from
              the first  URI appeared  in the  command line  or inside
              input files as usual.
  --npn-list=<LIST>
              Comma delimited list of  ALPN protocol identifier sorted
              in the  order of preference.  That  means most desirable
              protocol comes  first.  This  is used  in both  ALPN and
              NPN.  The parameter must be  delimited by a single comma
              only  and any  white spaces  are  treated as  a part  of
              protocol string.
              Default: h2,h2-16,h2-14,http/1.1
  --h1        Short        hand         for        --npn-list=http/1.1
              --no-tls-proto=http/1.1,    which   effectively    force
              http/1.1 for both http and https URI.
  --header-table-size=<SIZE>
              Specify decoder header table size.
              Default: 4K
  --encoder-header-table-size=<SIZE>
              Specify encoder header table size.  The decoder (server)
              specifies  the maximum  dynamic table  size it  accepts.
              Then the negotiated dynamic table size is the minimum of
              this option value and the value which server specified.
              Default: 4K
  -v, --verbose
              Output debug information.
  --version   Display version information and exit.
  -h, --help  Display this help and exit.

--

  The <SIZE> argument is an integer and an optional unit (e.g., 10K is
  10 * 1024).  Units are K, M and G (powers of 1024).

  The <DURATION> argument is an integer and an optional unit (e.g., 1s
  is 1 second and 500ms is 500 milliseconds).  Units are h, m, s or ms
  (hours, minutes, seconds and milliseconds, respectively).  If a unit
  is omitted, a second is used as unit.