项目作者: Nordix

项目描述 :
Keep-alive http test program
高级语言: Go
项目地址: git://github.com/Nordix/kahttp.git
创建时间: 2019-04-02T11:23:16Z
项目社区:https://github.com/Nordix/kahttp

开源协议:MIT License

下载


kahttp - Keep-alive http test program

This test program is intended for testing many simultaneous
(keep-alive) http connections. It is not intended for throughput or
latency measurements but is designed to test the limit for how many
simultaneous client connectons a http server or proxy can handle.

Build

  1. ./build.sh image
  2. ls ./image/kahttp

Usage

Local usage;

  1. # Start server;
  2. kahttp -server -address [::]:5080
  3. # In another shell;
  4. wget -q -O - http://127.0.0.1:5080/
  5. kahttp -address http://127.0.0.1:5080/ -monitor -rate 400 -nclients 40 -timeout 10s | jq .
  6. # In yet another shell;
  7. tcpdump -ni lo 'tcp[tcpflags] == tcp-syn'
  8. # Or for ipv6;
  9. tcpdump -ni lo tcp and 'ip6[13+40]&0x2!=0'

One way to verify that keep-alive is used done is to trace the SYN
packets with tcpdump. If there are an initial burst of and then
silence keep-alive is used. A steady stream os SYNs indicates that
keep-alive is not used.

Deploy a kahttp server on Kubernetes;

  1. kubectl apply -f https://raw.githubusercontent.com/Nordix/kahttp/master/kahttp.yaml

NOTE: The server is very primitive and is intended for simple tests only.

The server will use an internal self-signed certificate for https by
default. See below for an instruction howto use a k8s tls secret.

Measure keep-alive connections

Kahttp starts a number of http clients according to the -nclients
parameter. Each of these clients will make periodic http GET requests
towards the URL specified by the -address parameter. The -rate
parameter specifies the total number of http requests per
second. This is divided among the clients so a rate of 400 and 40
clients will result in 10 requests per second per client. The
keep-alive time is limited (but different) on servers so to make sure
connections are kept a certain rate per client must be maintained.

The key metric for measuring keep-alive connections is Dials. This
is the total number of actual TCP connects that the clients do. Below
is an example where all connections are kept;

  1. > kahttp -address http://127.0.0.1:5080/ -monitor -rate 400 -nclients 40 -timeout 10s | jq .
  2. Clients act/fail/Dials: 40/0/40, Packets send/rec/dropped: 399/399/0
  3. Clients act/fail/Dials: 40/0/40, Packets send/rec/dropped: 799/799/0
  4. Clients act/fail/Dials: 40/0/40, Packets send/rec/dropped: 1199/1199/0
  5. Clients act/fail/Dials: 40/0/40, Packets send/rec/dropped: 1600/1600/0
  6. Clients act/fail/Dials: 40/0/40, Packets send/rec/dropped: 2000/2000/0
  7. Clients act/fail/Dials: 40/0/40, Packets send/rec/dropped: 2400/2400/0
  8. Clients act/fail/Dials: 40/0/40, Packets send/rec/dropped: 2800/2800/0
  9. Clients act/fail/Dials: 40/0/40, Packets send/rec/dropped: 3200/3200/0
  10. Clients act/fail/Dials: 40/0/40, Packets send/rec/dropped: 3600/3600/0
  11. {
  12. "Started": "2019-04-02T13:02:06.815903366+02:00",
  13. "Duration": 10000112870,
  14. "Rate": 400,
  15. "Clients": 40,
  16. "Dials": 40,
  17. "FailedConnections": 0,
  18. "Sent": 3999,
  19. "Received": 3999,
  20. "Dropped": 0,
  21. "FailedConnects": 0
  22. }

In this case we have 40 clients making 3999 requests in total but the
number of Dials is 40, so each client make only one connection which
is kept alive for the entire run.

This shows the case where keep-alive is disabled using the
-disable_ka flag;

  1. # kahttp -nclients 10 -monitor -address https://10.0.0.2/ -host_stats -disable_ka | jq .
  2. Clients act/fail/Dials: 10/0/10, Packets send/rec/dropped: 10/10/0
  3. Clients act/fail/Dials: 10/0/20, Packets send/rec/dropped: 20/20/0
  4. Clients act/fail/Dials: 10/0/30, Packets send/rec/dropped: 30/30/0
  5. Clients act/fail/Dials: 10/0/40, Packets send/rec/dropped: 40/40/0
  6. Clients act/fail/Dials: 10/0/50, Packets send/rec/dropped: 50/50/0
  7. Clients act/fail/Dials: 10/0/60, Packets send/rec/dropped: 60/60/0
  8. Clients act/fail/Dials: 10/0/70, Packets send/rec/dropped: 70/70/0
  9. Clients act/fail/Dials: 10/0/80, Packets send/rec/dropped: 80/80/0
  10. Clients act/fail/Dials: 10/0/90, Packets send/rec/dropped: 90/90/0
  11. {
  12. "Started": "2019-04-06T08:18:09.44414217Z",
  13. "Duration": 9897737610,
  14. "Rate": 10,
  15. "Clients": 10,
  16. "Dials": 100,
  17. "FailedConnections": 0,
  18. "Sent": 100,
  19. "Received": 100,
  20. "Dropped": 0,
  21. "FailedConnects": 0,
  22. "Hosts": {
  23. "kahttp-deployment-ff8b6966-2cjw6": 26,
  24. "kahttp-deployment-ff8b6966-j45fw": 24,
  25. "kahttp-deployment-ff8b6966-plvqn": 26,
  26. "kahttp-deployment-ff8b6966-t867d": 24
  27. }
  28. }

The number of Dials is equal to the number of Sent requests. This
means that no connection is kept alive.

Server host statistics

The example above uses the -host_stats to get server host
statistics. Server host statistics only works if the server is
kahttp. The kahttp server returns the hostname of the server in
the body and in the X-Kahttp-Server-Host: http header. The kahttp
client collect the statistics and presents the number of requests to
each host.

This functions is not usable for keep-alive testing (the main purpose
of kahttp) but may be used for instance to test a
canary
setup. When -host_stats is used you should most likely also disable
keep-alive with -disable_ka.

Server access logging

Access to the server can be logged (to stdout). This may be useful for
debugging and tests of low intensity traffic such as health probing.

NOTE: Extensive logging will affect performance.

Server access logging is initiated with the -log-access parameter or
the $LOG_ACCESS environment variable. The parameter specifies a
sub-path to be logged or “/“ to log everything.

  1. $ ./image/kahttp -server -address :7000 -log-access /metrics
  2. 2020-07-11 13:02:39; localhost:7000/metrics from 127.0.0.1:43660
  3. 2020-07-11 13:02:39; localhost:7000/metrics from 127.0.0.1:43662
  4. 2020-07-11 13:02:39; localhost:7000/metrics from 127.0.0.1:43664
  5. ...

The log format is “date; from “.

Multiple source addresses

For testing of very many connections it is essential that the
connections originates from many sources. If just one (prominent)
source is used there will likely be a shortage of connection resources
since the src/dest addresses are always the same, only the ports can
be varied. The resource problem does not have to occur on the
endpoints but can be in network elements (NE) in between such as
load-balancers or NAT boxes.

To use many source addresses you must first assign a CIDR to the
loopback interface as described for
mconnect. Then
use;

  1. kahttp -address http://127.0.0.1:5080/ -monitor -rate 400 -nclients 40 \
  2. -timeout 10s -scrcidr 222.222.222.0/24

Set source address

Some times the source address must be set for instance to use a
specific ip-family as described in #6.

The -scrcidr can be used for this purpose but with masks /32 and /128;

  1. $ kahttp kahttp -address http://vm-001/cgi-bin/info -monitor -timeout 5s -srccidr 192.168.1.3/32
  2. ... (ipv4 used)
  3. $ kahttp kahttp -address http://vm-001/cgi-bin/info -monitor -timeout 5s -srccidr 1000::1:c0a8:103/128
  4. ... (ipv6 used)

Https

Kahttp disables certificate verification because the server is most
likely using a self-signed certificate. There is currently no way of
enabling certificate verification in the kahttp client.

The kahttp server will expose a https server if both -https_key
and -https_cert are specified (or the corresponding environment
variables $KAHTTP_KEY and $KAHTTP_CERT are set). The address
(including the port) can be specified with the -https_addr option
(default “:5443”).

Implementation is based on this
description.

Example;

  1. export KAHTTP_KEY=/tmp/server.key
  2. export KAHTTP_CERT=/tmp/server.crt
  3. openssl genrsa -out $KAHTTP_KEY 2048
  4. openssl req -new -x509 -sha256 -key $KAHTTP_KEY -out $KAHTTP_CERT -days 3650
  5. kahttp -server -address [::]:5080
  6. # In another shell;
  7. wget --no-check-certificate -qO- https://[::1]:5443/
  8. # Or;
  9. kahttp -address https://[::1]:5443/ -monitor -rate 400 -nclients 40 -timeout 10s | jq .

If you use another client, e.g. curl you can verify the self-signed
certificate. First the “Common name” used must match the request
url. Use the --resolv option, for example;

  1. curl -v --cacert /tmp/server.crt --resolv kahttp.localdomain:5443:[::1] \
  2. https://kahttp.localdomain:5443/

Client certificate, mTLS

Kahttp accepts and verifies client certificates if given
(tls.VerifyClientCertIfGiven). Http requests without client
certificate or with a correct certificate are accepted but requests
with an invalid certificate are rejected.

  1. curl -v --cacert /tmp/server.crt --resolv kahttp.localdomain:5443:[::1] \
  2. --cert /tmp/server.crt --key /tmp/server.key \
  3. https://kahttp.localdomain:5443/
  4. ...
  5. * TLSv1.2 (OUT), TLS handshake, CERT verify (15):

The same certificate as for the server is presented as a client
certificate which is valid and the (faked) header
CERT verify indicates that a client certificate is used.

If an invalid client certificate is used the conneciton fails;

  1. curl --cacert /tmp/server.crt --resolv kahttp.localdomain:5443:[::1] \
  2. --cert /tmp/kahttp.crt --key /tmp/kahttp.key \
  3. https://kahttp.localdomain:5443/
  4. ...
  5. curl: (35) error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate

Http2

Curl uses http/2 by default, use the --http1.1 option to enforce
http1. Use the -http2 flag to make the kahttp client to use
http2. Http2 used on a clear-text connection (http) is converted to h2c.

  1. curl --insecure --http1.1 --resolv kahttp.localdomain:5443:[::1] https://[::1]:5443/
  2. kahttp -address https://[::1]:5443/ -monitor -http2 -rate 400 -nclients 40 -timeout 10s | jq .
  3. # This will use h2c;
  4. curl -D - --http2 http://[::1]:5443/
  5. # This will not work;
  6. kahttp -address http://[::1]:5443/ -http2

Use a k8s tls secret

First create a k8s tls secret from the crt and key files;

  1. kubectl create secret tls kahttp-secret --key /cert/kahttp.key --cert /cert/kahttp.crt

In the kahttp manifest mount the secret and set the KAHTTP_KEY and
KAHTTP_CERT variables appropriately (see
kahttp-secret.yaml);

  1. ...
  2. env:
  3. - name: KAHTTP_KEY
  4. value: "/cert/tls.key"
  5. - name: KAHTTP_CERT
  6. value: "/cert/tls.crt"
  7. volumeMounts:
  8. - name: cert
  9. mountPath: "/cert"
  10. readOnly: true
  11. volumes:
  12. - name: cert
  13. secret:
  14. secretName: kahttp-secret