Skip to content

Commit

Permalink
Adding fan out forwarder http proxy mode (-M ...) (fortio#410)
Browse files Browse the repository at this point in the history
* Adding fan out forwarder http proxy mode (-M ...)

* linters and coverage increase

* bug fix on header transfers for tracing. increase converage/error cases

* default MaxIdleConnsPerHost is 2 (!) which killed perf for any kind of parallelization. set better default

Fixes fortio#160
  • Loading branch information
ldemailly authored Oct 7, 2020
1 parent 4f6bbfb commit 7e86560
Show file tree
Hide file tree
Showing 6 changed files with 389 additions and 58 deletions.
135 changes: 97 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The name fortio comes from greek [φορτίο](https://fortio.org/fortio.mp3) w
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, GRPC echo/health in addition to http, etc...
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.
Expand All @@ -44,13 +44,13 @@ docker run fortio/fortio load http://www.google.com/ # For a test run
Or download one of the binary distributions, from the [releases](https://github.com/fortio/fortio/releases) assets page or for instance:

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

On a MacOS you can also install Fortio using [Homebrew](https://brew.sh/):
Expand All @@ -59,7 +59,7 @@ On a MacOS you can also install Fortio using [Homebrew](https://brew.sh/):
brew install fortio
```

On Windows, download https://github.com/fortio/fortio/releases/download/v1.8.1/fortio_win_1.8.1.zip and extract all to some location then using the Windows Command Prompt:
On Windows, download https://github.com/fortio/fortio/releases/download/v1.9.0/fortio_win_1.9.0.zip and extract all to some location then using the Windows Command Prompt:
```
cd fortio
fortio.exe server
Expand Down Expand Up @@ -103,21 +103,24 @@ Full list of command line flags (`fortio help`):
<details>
<!-- use release/updateFlags.sh to update this section -->
<pre>
Φορτίο 1.8.1 usage:
Φορτίο 1.9.0 usage:
fortio command [flags] target
where command is one of: load (load testing), server (starts ui, http-echo,
redirect, proxies, tcp-echo and grpc ping servers), tcp-echo (only the tcp-echo
server), report (report only UI server), redirect (only the redirect server),
grpcping (grpc client), or curl (single URL debug), or nc (single tcp
connection).
proxies (only the -M and -P configured proxies), grpcping (grpc client),
or curl (single URL debug), or nc (single tcp connection).
where target is a url (http load tests) or host:port (grpc health test).
flags are:
-H header
Additional header(s)
-L Follow redirects (implies -std-client) - do not use for load test
-M value
Http multi proxy to run, e.g -M "localport1 baseDestURL1 baseDestURL2"
-M ...
-P value
Proxies to run, e.g -P "localport1 dest_host1:dest_port1" -P "[::1]:0
www.google.com:443" ...
Tcp proxies to run, e.g -P "localport1 dest_host1:dest_port1" -P
"[::1]:0 www.google.com:443" ...
-a Automatically save JSON result with filename based on labels & timestamp
-abort-on code
Http code that if encountered aborts the run. e.g. 503 or -1 for socket
Expand Down Expand Up @@ -206,6 +209,9 @@ target URL and hostname
-maxpayloadsizekb Kbytes
MaxPayloadSize is the maximum size of payload to be generated by the
EchoHandler size= argument. In Kbytes. (default 256)
-multi-mirror-origin
Mirror the request url to the target for multi proxies (-M) (default
true)
-n int
Run for exactly this number of calls instead of duration. Default (0)
is to use duration (-t). Default is 1 when used as grpc ping count.
Expand Down Expand Up @@ -274,15 +280,15 @@ See also the FAQ entry about [fortio flags for best results](https://github.com/
```Shell
$ fortio server &
14:11:05 I fortio_main.go:171> Not using dynamic flag watching (use -config to set watch directory)
Fortio 1.8.1 tcp-echo server listening on [::]:8078
Fortio 1.8.1 grpc 'ping' server listening on [::]:8079
Fortio 1.8.1 https redirector server listening on [::]:8081
Fortio 1.8.1 echo server listening on [::]:8080
Fortio 1.9.0 tcp-echo server listening on [::]:8078
Fortio 1.9.0 grpc 'ping' server listening on [::]:8079
Fortio 1.9.0 https redirector server listening on [::]:8081
Fortio 1.9.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.8.1 release go1.15.2 servers started!
14:11:05 I fortio_main.go:233> All fortio 1.9.0 release go1.15.2 servers started!
```

### Change the port / binding address
Expand All @@ -295,8 +301,8 @@ $ 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.8.1 grpc ping server listening on port :8079
Fortio 1.8.1 echo server listening on port 10.10.10.10:8088
Fortio 1.9.0 grpc ping server listening on port :8079
Fortio 1.9.0 echo server listening on port 10.10.10.10:8088
```

### Unix domain sockets
Expand All @@ -305,27 +311,27 @@ You can use unix domain socket for any server/client:

```Shell
$ fortio server --http-port /tmp/fortio-uds-http &
Fortio 1.8.1 grpc 'ping' server listening on [::]:8079
Fortio 1.8.1 https redirector server listening on [::]:8081
Fortio 1.8.1 echo server listening on /tmp/fortio-uds-http
Fortio 1.9.0 grpc 'ping' server listening on [::]:8079
Fortio 1.9.0 https redirector server listening on [::]:8081
Fortio 1.9.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.8.1 unknown go1.10.3 servers started!
14:58:45 I fortio_main.go:217> All fortio 1.9.0 unknown go1.10.3 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.8.1 unknown go1.10.3 echo debug server up for 2m3.4s on ldemailly-macbookpro - request from
Φορτίο version 1.9.0 unknown go1.10.3 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.8.1
User-Agent: fortio.org/fortio-1.9.0

body:
```
Expand All @@ -334,10 +340,10 @@ body:
Start the echo-server alone and run a load (use `tcp://` prefix for the load test to be for tcp echo server)
```Shell
$ fortio echo-server &
Fortio 1.8.1 tcp-echo server listening on [::]:8078
19:45:30 I fortio_main.go:238> All fortio 1.8.1 release go1.15.2 servers started!
Fortio 1.9.0 tcp-echo server listening on [::]:8078
19:45:30 I fortio_main.go:238> All fortio 1.9.0 release go1.15.2 servers started!
$ load -qps -1 -n 100000 tcp://localhost:8078
Fortio 1.8.1 running at -1 queries per second, 16->16 procs, for 100000 calls: tcp://localhost:8078
Fortio 1.9.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
Expand Down Expand Up @@ -408,8 +414,8 @@ $ 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.8.1 grpc ping server listening on port :8079
Fortio 1.8.1 echo server listening on port localhost:8080
Fortio 1.9.0 grpc ping server listening on port :8079
Fortio 1.9.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
```
Expand Down Expand Up @@ -454,7 +460,7 @@ Load (low default qps/threading) test:

```Shell
$ fortio load http://www.google.com
Fortio 1.8.1 running at 8 queries per second, 8->8 procs, for 5s: http://www.google.com
Fortio 1.9.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
Expand Down Expand Up @@ -485,7 +491,7 @@ Uses `-s` to use multiple (h2/grpc) streams per connection (`-c`), request to hi

```bash
$ fortio load -a -grpc -ping -grpc-ping-delay 0.25s -payload "01234567890" -c 2 -s 4 https://fortio-stage.istio.io
Fortio 1.8.1 running at 8 queries per second, 8->8 procs, for 5s: https://fortio-stage.istio.io
Fortio 1.9.0 running at 8 queries per second, 8->8 procs, for 5s: https://fortio-stage.istio.io
16:32:56 I grpcrunner.go:139> Starting GRPC Ping Delay=250ms PayloadLength=11 test for https://fortio-stage.istio.io with 4*2 threads at 8.0 qps
16:32:56 I grpcrunner.go:261> stripping https scheme. grpc destination: fortio-stage.istio.io. grpc port: 443
16:32:57 I grpcrunner.go:261> stripping https scheme. grpc destination: fortio-stage.istio.io. grpc port: 443
Expand Down Expand Up @@ -590,14 +596,14 @@ Content-Type: text/plain; charset=UTF-8
Date: Mon, 08 Jan 2018 22:26:26 GMT
Content-Length: 230

Φορτίο version 1.8.1 echo debug server up for 39s on ldemailly-macbookpro - request from [::1]:65055
Φορτίο version 1.9.0 echo debug server up for 39s on ldemailly-macbookpro - request from [::1]:65055

GET /debug HTTP/1.1

headers:

Host: localhost:8080
User-Agent: fortio.org/fortio-1.8.1
User-Agent: fortio.org/fortio-1.9.0
Foo: Bar

body:
Expand All @@ -615,21 +621,74 @@ http://localhost:8080/
Https redirector running on :8081
```

### Using the HTTP fan out / multi proxy feature

Example listen on 1 extra port and every request sent to that 1 port is forward to 2:
```Shell
# in one window or &
$ fortio server -M "5554 http://localhost:8080 http://localhost:8080"
[...]
Fortio 1.9.0 Multi on 5554 server listening on [::]:5554
10:09:56 I http_forwarder.go:152> Multi-server on [::]:5554 running with &{Targets:[{Destination:http://localhost:8080 MirrorOrigin:true} {Destination:http://localhost:8080 MirrorOrigin:true}] Name:Multi on [::]:5554 client:0xc0001ccc00}
```
Call the debug endpoint on both
```Shell
# in new window
$ fortio curl -payload "a test" http://localhost:5554/debug
HTTP/1.1 200 OK
Date: Wed, 07 Oct 2020 17:11:06 GMT
Content-Length: 684
Content-Type: text/plain; charset=utf-8

Φορτίο version 1.9.0 unknown go1.15.2 echo debug server up for 1m9.3s on C02C77BHMD6R - request from [::1]:51020

POST /debug HTTP/1.1

headers:

Host: localhost:8080
Accept-Encoding: gzip
Content-Type: application/octet-stream
User-Agent: fortio.org/fortio-1.9.0
X-Fortio-Multi-Id: 1
X-On-Behalf-Of: [::1]:51019

body:

a test
Φορτίο version 1.9.0 unknown go1.15.2 echo debug server up for 1m9.3s on C02C77BHMD6R - request from [::1]:51020

POST /debug HTTP/1.1

headers:

Host: localhost:8080
Accept-Encoding: gzip
Content-Type: application/octet-stream
User-Agent: fortio.org/fortio-1.9.0
X-Fortio-Multi-Id: 2
X-On-Behalf-Of: [::1]:51019

body:

a test
```

### Using the TCP proxy server(s) feature

Example: open 2 additional listening ports and forward all requests received on 8888 and 8889 (ipv6) to 8080 (regular http server)

```Shell
$ fortio server -P "8888 [::1]:8080" -P "[::1]:8889 [::1]:8080"
Fortio 1.8.1 grpc 'ping' server listening on [::]:8079
Fortio 1.8.1 https redirector server listening on [::]:8081
Fortio 1.8.1 echo server listening on [::]:8080
Fortio 1.9.0 grpc 'ping' server listening on [::]:8079
Fortio 1.9.0 https redirector server listening on [::]:8081
Fortio 1.9.0 echo server listening on [::]:8080
Data directory is /home/dl
UI started - visit:
http://localhost:8080/fortio/
(or any host/ip reachable on this server)
Fortio 1.8.1 proxy for [::1]:8080 server listening on [::]:8888
Fortio 1.8.1 proxy for [::1]:8080 server listening on [::1]:8889
Fortio 1.9.0 proxy for [::1]:8080 server listening on [::]:8888
Fortio 1.9.0 proxy for [::1]:8080 server listening on [::1]:8889
```

## Server URLs and features
Expand Down
Loading

0 comments on commit 7e86560

Please sign in to comment.