Shopify / toxiproxy

:alarm_clock: :fire: A TCP proxy to simulate network and system conditions for chaos and resiliency testing
https://github.com/shopify/toxiproxy
MIT License
10.64k stars 445 forks source link

Optional upstream? #155

Open dentarg opened 7 years ago

dentarg commented 7 years ago

This might only make sense for the timeout toxic used with timeout=0, but wouldn't it be nice if it could work without a responding upstream?

I tried with a "dummy" upstream, just picking a port where nothing was listening

[
  {
    "name": "timeout_dummy",
    "listen": "127.0.0.1:8080",
    "upstream": "127.0.0.1:9999"
  }
]
$ toxiproxy-cli toxic add timeout_dummy -t timeout -a timeout=0
Added downstream timeout toxic 'timeout_downstream' on proxy 'timeout_dummy'

But toxiproxy didn't like that

$ curl -o /dev/null -s -v -m 3 http://127.0.0.1:8080
* Rebuilt URL to: http://127.0.0.1:8080/
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
* Empty reply from server
* Connection #0 to host 127.0.0.1 left intact
$ toxiproxy-server -config tmp/toxiproy.json
INFO[0000] Started proxy                                 name=timeout_dummy proxy=127.0.0.1:8080 upstream=127.0.0.1:9999
INFO[0000] Populated proxies from file                   config=tmp/toxiproy.json proxies=1
INFO[0000] API HTTP server starting                      host=localhost port=8474 version=2.1.0
INFO[0004] Accepted client                               client=127.0.0.1:62301 name=timeout_dummy proxy=127.0.0.1:8080 upstream=127.0.0.1:9999
ERRO[0004] Unable to open connection to upstream         client=127.0.0.1:62301 name=timeout_dummy proxy=127.0.0.1:8080 upstream=127.0.0.1:9999

I was actually able to workaround this by setting the upstream to toxiproxy itself ("upstream": "127.0.0.1:8474"):

$ toxiproxy-server -config tmp/toxiproy.json
INFO[0000] Started proxy                                 name=timeout_dummy proxy=127.0.0.1:8080 upstream=127.0.0.1:8474
INFO[0000] Populated proxies from file                   config=tmp/toxiproy.json proxies=1
INFO[0000] API HTTP server starting                      host=localhost port=8474 version=2.1.0
INFO[0017] Accepted client                               client=127.0.0.1:62254 name=timeout_dummy proxy=127.0.0.1:8080 upstream=127.0.0.1:8474
WARN[0020] Source terminated                             bytes=176 err=read tcp 127.0.0.1:62255->127.0.0.1:8474: use of closed network connection name=timeout_dummy
$ curl -o /dev/null -s -v -m 3 http://127.0.0.1:8080
* Rebuilt URL to: http://127.0.0.1:8080/
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
* Operation timed out after 3002 milliseconds with 0 bytes received
* Closing connection 0

WDYT about the workaround, might be enough that that works?

sirupsen commented 7 years ago

This is not a bad idea... I'm wondering if there are other use-cases where not having an upstream is useful. For example, would it make sense to have the latency toxic take an optional argument of a response to send back to the client, without an upstream?

dentarg commented 7 years ago

I think it make sense in many cases, to be able to specify the response, when the resource your are simulating is an external HTTP resource, which is my use-case... :)

I was first looking at pathod, which seems really nice, but I didn't find out (might not be possible) to make it simulate a timeout, like Toxiproxy.

I think this subject somewhat ties into #50 (maybe just to make it easier to pick between some common responses)

sirupsen commented 7 years ago

Yeah, this might actually not be too hard with the work that's going into #50 for 2.2. Jacob can add some more thought on this :)

xthexder commented 7 years ago

I've thought about this for things like protocol aware toxics where you could potentially mock out the backend server entirely. There's definitely a few applications for it, it's just a matter of figuring out a good way to specify backend type.

Currently the connection is made to the backend as soon as a client connects, and return immediately if it's down, regardless of toxics. This means whatever the settings is, it would need to be on the proxy, not a toxic. Maybe a special noop or blank upstream would be enough to tell the proxy not to connect to a backend?

dentarg commented 7 years ago

Maybe a special noop or blank upstream would be enough to tell the proxy not to connect to a backend?

Sounds good