VOOZH about

URL: https://hub.docker.com/r/istio/fortio

⇱ istio/fortio - Docker Image


istio/fortio

Sponsored OSS

By istio

Updated almost 5 years ago

Fortio load testing library and tool in go. Allows a set qps load and records latency histograms.

Image
1

1M+

istio/fortio repository overview

Fortio

👁 Awesome Go
👁 Go Report Card
👁 GoDoc
👁 codecov
👁 CircleCI
👁 Docker Build
👁 Docker Pulls
👁 Image

Fortio (Φορτίο) started as, and is, Istio's load testing tool and now graduated to be its own project.

Fortio is also used by, among others, Meshery

Fortio runs at a specified query per second (qps) and records an histogram of execution time and calculates percentiles (e.g. p99 ie the response time such as 99% of the requests take less than that number (in seconds, SI unit)). It can run for a set duration, for a fixed number of calls, or until interrupted (at a constant target QPS, or max speed/load per connection/thread).

The name fortio comes from greek φορτίο which means load/burden.

Fortio is a fast, small (3Mb docker image, minimal dependencies), reusable, embeddable go library as well as a command line tool and server process, the server includes a simple web UI and graphical representation of the results (both a single latency graph and a multiple results comparative min, max, avg, qps and percentiles graphs).

Fortio also includes a set of server side features (similar to httpbin) to help debugging and testing: request echo back including headers, adding latency or error codes with a probability distribution, tcp echoing, tcp proxying, http fan out/scatter and gather proxy server, GRPC echo/health in addition to http, etc...

Fortio is quite mature and very stable with no known major bugs (lots of possible improvements if you want to contribute though!), and when bugs are found they are fixed quickly, so after 1 year of development and 42 incremental releases, we reached 1.0 in June 2018.

Fortio components can be used a library even for unrelated projects, for instance the log, stats, or fhttp utilities both client and server. As well as the newly integrated Dynamic Flags support (greatly inspired/imported initially from https://github.com/mwitkow/go-flagz)

Installation

  1. Install go (golang 1.16 or later)
  2. go get fortio.org/fortio
  3. you can now run fortio (from your gopath bin/ directory)

Or use docker, for instance:

docker run -p 8080:8080 -p 8079:8079 fortio/fortio server & # For the server
docker run fortio/fortio load http://www.google.com/ # For a test run

Or download one of the binary distributions, from the releases assets page or for instance:

curl -L https://github.com/fortio/fortio/releases/download/v1.17.0/fortio-linux_x64-1.17.0.tgz \
 | sudo tar -C / -xvzpf -
# or the debian package
wget https://github.com/fortio/fortio/releases/download/v1.17.0/fortio_1.17.0_amd64.deb
dpkg -i fortio_1.17.0-1_amd64.deb
# or the rpm
rpm -i https://github.com/fortio/fortio/releases/download/v1.17.0/fortio-1.17.0-1.x86_64.rpm

On a MacOS you can also install Fortio using Homebrew:

brew install fortio

On Windows, download https://github.com/fortio/fortio/releases/download/v1.17.0/fortio_win_1.17.0.zip and extract all to some location then using the Windows Command Prompt:

cd fortio
fortio.exe server

(at the prompt, allow the windows firewall to let connections in)

Once fortio server is running, you can visit its web UI at http://localhost:8080/fortio/

You can get a preview of the reporting/graphing UI at https://fortio.istio.io/ and on istio.io/docs/performance-and-scalability/synthetic-benchmarks/

Command line arguments

Fortio can be an http or grpc load generator, gathering statistics using the load subcommand, or start simple http and grpc ping servers, as well as a basic web UI, result graphing, tcp/udp echo, proxies, https redirector, with the server command or issue grpc ping messages using the grpcping command. It can also fetch a single URL's for debugging when using the curl command (or the -curl flag to the load command). Likewise you can establish a single TCP (or unix domain or UDP (use udp:// prefix)) connection using the nc command (like the standalone netcat package). You can run just the redirector with redirect or just the tcp echo with tcp-echo. If you saved JSON results (using the web UI or directly from the command line), you can browse and graph those results using the report command. The version command will print version and build information, fortio version -s just the version. Lastly, you can learn which flags are available using help command.

Most important flags for http load generation:

FlagDescription, example
-qps rateQueries Per Seconds or 0 for no wait/max qps
-c connectionsNumber of parallel simultaneous connections (and matching go routine)
-t durationHow long to run the test (for instance -t 30m for 30 minutes) or 0 to run until ^C, example (default 5s)
-n numcallsRun for exactly this number of calls instead of duration. Default (0) is to use duration (-t).
-r resolutionResolution of the histogram lowest buckets in seconds (default 0.001 i.e 1ms), use 1/10th of your expected typical latency
-H "header: value"Can be specified multiple times to add headers (including Host:)
-aAutomatically save JSON result with filename based on labels and timestamp
-json filenameFilename or - for stdout to output json result (relative to -data-dir by default, should end with .json if you want fortio report to show them; using -a is typicallly a better option)
-labels "l1 l2 ..."Additional config data/labels to add to the resulting JSON, defaults to target URL and hostname

You can switch from http GET queries to POST by setting -content-type or passing one of the -payload-* option.

Full list of command line flags (fortio help):

See also the FAQ entry about fortio flags for best results

Example use and output

Start the internal servers
$ fortio server &
14:11:05 I fortio_main.go:171> Not using dynamic flag watching (use -config to set watch directory)
Fortio 1.17.0 tcp-echo server listening on [::]:8078
Fortio 1.17.0 grpc 'ping' server listening on [::]:8079
Fortio 1.17.0 https redirector server listening on [::]:8081
Fortio 1.17.0 echo server listening on [::]:8080
Data directory is /Users/ldemailly/go/src/fortio.org/fortio
UI started - visit:
http://localhost:8080/fortio/
(or any host/ip reachable on this server)
14:11:05 I fortio_main.go:233> All fortio 1.17.0 release go1.16.5 servers started!
Change the port / binding address

By default, Fortio's web/echo servers listen on port 8080 on all interfaces. Use the -http-port flag to change this behavior:

$ fortio server -http-port 10.10.10.10:8088
UI starting - visit:
http://10.10.10.10:8088/fortio/
Https redirector running on :8081
Fortio 1.17.0 grpc ping server listening on port :8079
Fortio 1.17.0 echo server listening on port 10.10.10.10:8088
Unix domain sockets

You can use unix domain socket for any server/client:

$ fortio server --http-port /tmp/fortio-uds-http &
Fortio 1.17.0 grpc 'ping' server listening on [::]:8079
Fortio 1.17.0 https redirector server listening on [::]:8081
Fortio 1.17.0 echo server listening on /tmp/fortio-uds-http
UI started - visit:
fortio curl -unix-socket=/tmp/fortio-uds-http http://localhost/fortio/
14:58:45 I fortio_main.go:217> All fortio 1.17.0 unknown go1.16.5 servers started!
$ fortio curl -unix-socket=/tmp/fortio-uds-http http://foo.bar/debug
15:00:48 I http_client.go:428> Using unix domain socket /tmp/fortio-uds-http instead of foo.bar http
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Date: Wed, 08 Aug 2018 22:00:48 GMT
Content-Length: 231

Φορτίο version 1.17.0 unknown go1.16.5 echo debug server up for 2m3.4s on ldemailly-macbookpro - request from

GET /debug HTTP/1.1

headers:

Host: foo.bar
User-Agent: fortio.org/fortio-1.17.0

body:
TCP

Start the echo-server alone and run a load (use tcp:// prefix for the load test to be for tcp echo server)

$ fortio tcp-echo &
Fortio 1.17.0 tcp-echo TCP server listening on [::]:8078
19:45:30 I fortio_main.go:238> All fortio 1.17.0 release go1.16.5 servers started!
$ fortio load -qps -1 -n 100000 tcp://localhost:8078
Fortio 1.17.0 running at -1 queries per second, 16->16 procs, for 100000 calls: tcp://localhost:8078
20:01:31 I tcprunner.go:218> Starting tcp test for tcp://localhost:8078 with 4 threads at -1.0 qps
Starting at max qps with 4 thread(s) [gomax 16] for exactly 100000 calls (25000 per thread + 0)
20:01:32 I periodic.go:558> T003 ended after 1.240585427s : 25000 calls. qps=20151.77629520873
20:01:32 I periodic.go:558> T002 ended after 1.241141084s : 25000 calls. qps=20142.75437521493
20:01:32 I periodic.go:558> T001 ended after 1.242066385s : 25000 calls. qps=20127.7486468648
20:01:32 I periodic.go:558> T000 ended after 1.24227731s : 25000 calls. qps=20124.331176909283
Ended after 1.242312567s : 100000 calls. qps=80495
Aggregated Function Time : count 100000 avg 4.9404876e-05 +/- 1.145e-05 min 2.7697e-05 max 0.000887051 sum 4.94048763
# range, mid point, percentile, count
>= 2.7697e-05 <= 0.000887051 , 0.000457374 , 100.00, 100000
# target 50% 0.00045737
# target 75% 0.00067221
# target 90% 0.000801115
# target 99% 0.000878457
# target 99.9% 0.000886192
Sockets used: 4 (for perfect no error run, would be 4)
Total Bytes sent: 2400000, received: 2400000
tcp OK : 100000 (100.0 %)
All done 100000 calls (plus 0 warmup) 0.049 ms avg, 80495.0 qps
UDP

Start the udp-echo server alone and run a load (use tcp:// prefix for the load test to be for tcp echo server)

$ fortio udp-echo &
Fortio 1.17.0 udp-echo UDP server listening on [::]:8078
21:54:52 I fortio_main.go:273> Note: not using dynamic flag watching (use -config to set watch directory)
21:54:52 I fortio_main.go:281> All fortio 1.17.0 release go1.16.5 servers started!
$ fortio load -qps -1 -n 100000 udp://localhost:8078/
Fortio 1.17.0 running at -1 queries per second, 16->16 procs, for 100000 calls: udp://localhost:8078/
21:56:48 I udprunner.go:222> Starting udp test for udp://localhost:8078/ with 4 threads at -1.0 qps
Starting at max qps with 4 thread(s) [gomax 16] for exactly 100000 calls (25000 per thread + 0)
21:56:49 I periodic.go:558> T003 ended after 969.635695ms : 25000 calls. qps=25782.879208051432
21:56:49 I periodic.go:558> T000 ended after 969.906228ms : 25000 calls. qps=25775.687667818544
21:56:49 I periodic.go:558> T002 ended after 970.543935ms : 25000 calls. qps=25758.751457243405
21:56:49 I periodic.go:558> T001 ended after 970.737665ms : 25000 calls. qps=25753.610786287973
Ended after 970.755702ms : 100000 calls. qps=1.0301e+05
Aggregated Function Time : count 100000 avg 3.8532238e-05 +/- 1.7e-05 min 2.0053e-05 max 0.000881827 sum 3.85322376
# range, mid point, percentile, count
>= 2.0053e-05 <= 0.000881827 , 0.00045094 , 100.00, 100000
# target 50% 0.000450936
# target 75% 0.000666381
# target 90% 0.000795649
# target 99% 0.000873209
# target 99.9% 0.000880965
Sockets used: 4 (for perfect no error run, would be 4)
Total Bytes sent: 2400000, received: 2400000
udp OK : 100000 (100.0 %)
All done 100000 calls (plus 0 warmup) 0.039 ms avg, 103012.5 qps
GRPC
Simple grpc ping
$ fortio grpcping -n 5 localhost
22:36:55 I pingsrv.go:150> Ping RTT 212000 (avg of 259000, 217000, 160000 ns) clock skew -10500
22:36:55 I pingsrv.go:150> Ping RTT 134333 (avg of 170000, 124000, 109000 ns) clock skew 5000
22:36:55 I pingsrv.go:150> Ping RTT 112000 (avg of 111000, 122000, 103000 ns) clock skew 5000
22:36:55 I pingsrv.go:150> Ping RTT 157000 (avg of 136000, 158000, 177000 ns) clock skew 6000
22:36:55 I pingsrv.go:150> Ping RTT 108333 (avg of 118000, 106000, 101000 ns) clock skew 1000
Clock skew histogram usec : count 5 avg 1.3 +/- 6.145 min -10.5 max 6 sum 6.5
# range, mid point, percentile, count
>= -10.5 <= -10 , -10.25 , 20.00, 1
> 0 <= 2 , 1 , 40.00, 1
> 4 <= 6 , 5 , 100.00, 3
# target 50% 4.33333
RTT histogram usec : count 15 avg 144.73333 +/- 44.48 min 101 max 259 sum 2171
# range, mid point, percentile, count
>= 101 <= 110 , 105.5 , 26.67, 4
> 110 <= 120 , 115 , 40.00, 2
> 120 <= 140 , 130 , 60.00, 3
> 140 <= 160 , 150 , 73.33, 2
> 160 <= 180 , 170 , 86.67, 2
> 200 <= 250 , 225 , 93.33, 1
> 250 <= 259 , 254.5 , 100.00, 1
# target 50% 130
Change the target port for grpc

The value of -grpc-port (default 8079) is used when specifying a hostname or an IP address in grpcping. Add :port to the grpcping destination to change this behavior:

$ fortio grpcping 10.10.10.100:8078 # Connects to gRPC server 10.10.10.100 listening on port 8078
02:29:27 I pingsrv.go:116> Ping RTT 305334 (avg of 342970, 293515, 279517 ns) clock skew -2137
Clock skew histogram usec : count 1 avg -2.137 +/- 0 min -2.137 max -2.137 sum -2.137
# range, mid point, percentile, count
>= -4 < -2 , -3 , 100.00, 1
# target 50% -2.137
RTT histogram usec : count 3 avg 305.334 +/- 27.22 min 279.517 max 342.97 sum 916.002
# range, mid point, percentile, count
>= 250 < 300 , 275 , 66.67, 2
>= 300 < 350 , 325 , 100.00, 1
# target 50% 294.879
grpcping using TLS
  • First, start Fortio server with the -cert and -key flags:

/path/to/fortio/server.crt and /path/to/fortio/server.key are paths to the TLS certificate and key that you must provide.

$ fortio server -cert /path/to/fortio/server.crt -key /path/to/fortio/server.key
UI starting - visit:
http://localhost:8080/fortio/
Https redirector running on :8081
Fortio 1.17.0 grpc ping server listening on port :8079
Fortio 1.17.0 echo server listening on port localhost:8080
Using server certificate /path/to/fortio/server.crt to construct TLS credentials
Using server key /path/to/fortio/server.key to construct TLS credentials
  • Next, use grpcping with the -cacert flag:

/path/to/fortio/ca.crt is the path to the CA certificate that issued the server certificate for localhost. In our example, the server certificate is /path/to/fortio/server.crt:

$ fortio grpcping -cacert /path/to/fortio/ca.crt localhost
Using server certificate /path/to/fortio/ca.crt to construct TLS credentials
16:00:10 I pingsrv.go:129> Ping RTT 501452 (avg of 595441, 537088, 371828 ns) clock skew 31094
Clock skew histogram usec : count 1 avg 31.094 +/- 0 min 31.094 max 31.094 sum 31.094
# range, mid point, percentile, count
>= 31.094 <= 31.094 , 31.094 , 100.00, 1
# target 50% 31.094
RTT histogram usec : count 3 avg 501.45233 +/- 94.7 min 371.828 max 595.441 sum 1504.357
# range, mid point, percentile, count
>= 371.828 <= 400 , 385.914 , 33.33, 1
> 500 <= 595.441 , 547.721 , 100.00, 2
# target 50% 523.86
GRPC to standard https service

grpcping can connect to a non-Fortio TLS server by prefacing the destination with https://:

$ fortio grpcping https://fortio.istio.io
11:07:55 I grpcrunner.go:275> stripping https scheme. grpc destination: fortio.istio.io. grpc port: 443
Clock skew histogram usec : count 1 avg 12329.795 +/- 0 min 12329.795 max 12329.795 sum 12329.795
# range, mid point, percentile, count
>= 12329.8 <= 12329.8 , 12329.8 , 100.00, 1
# target 50% 12329.8
Simple load test

Load (low default qps/threading) test:

$ fortio load http://www.google.com
Fortio 1.17.0 running at 8 queries per second, 8->8 procs, for 5s: http://www.google.com
19:10:33 I httprunner.go:84> Starting http test for http://www.google.com with 4 threads at 8.0 qps
Starting at 8 qps with 4 thread(s) [gomax 8] for 5s : 10 calls each (total 40)
19:10:39 I periodic.go:314> T002 ended after 5.056753279s : 10 calls. qps=1.9775534712220633
19:10:39 I periodic.go:314> T001 ended after 5.058085991s : 10 calls. qps=1.9770324224999916
19:10:39 I periodic.go:314> T000 ended after 5.058796046s : 10 calls. qps=1.9767549252963101
19:10:39 I periodic.go:314> T003 ended after 5.059557593s : 10 calls. qps=1.9764573910247019
Ended after 5.059691387s : 40 calls. qps=7.9056
Sleep times : count 36 avg 0.49175757 +/- 0.007217 min 0.463508712 max 0.502087879 sum 17.7032725
Aggregated Function Time : count 40 avg 0.060587641 +/- 0.006564 min 0.052549016 max 0.089893269 sum 2.42350566
# range, mid point, percentile, count
>= 0.052549 < 0.06 , 0.0562745 , 47.50, 19
>= 0.06 < 0.07 , 0.065 , 92.50, 18
>= 0.07 < 0.08 , 0.075 , 97.50, 2
>= 0.08 <= 0.0898933 , 0.0849466 , 100.00, 1
# target 50% 0.0605556
# target 75

Tag summary

latest

Content type

Image

Digest

Size

4.4 MB

Last updated

almost 5 years ago

Requires Docker Desktop 4.37.1 or later.

This week's pulls

Pulls:

248

Last week