jakub holý

building the right thing, building it right, fast

Java: Simulating various connection problems with Toxiproxy

2018-11-26Languages

Java: Simulating various connection problems with Toxiproxy

Simulate various connection issues with Toxiproxy and Java's HttpURLConnection to see what kind of errors get produced: connect timed out vs. read timed out vs. connection refused ... .

Results:

System: openjdk 11.0.1 2018-10-16

  1. (.setConnectTimeout 1) => java.net.SocketTimeoutException: connect timed out
  2. (.setReadTimeout 1) => javax.net.ssl.SSLProtocolException: Read timed out on HTTPS, java.net.SocketTimeoutException: Read timed out on HTTP (or Toxiproxy with 5s latency or timeout )
  3. Nothing listening at the port => java.net.ConnectException: Connection refused
  4. Toxiproxy with no upstream configured (i.e. the port is open, but nothing happesn with the connection) => javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake on HTTPS, java.net.SocketTimeoutException: Read timed out on HTTP
  5. limit_data_downstream => java.io.IOException: Premature EOF

(What I haven't been able to simulate (yet) is "connection interrupted/broken", i.e. java.net.SocketException Connection reset (perhaps you closed it and try to write to it anyway?) and java.net.SocketException Connection reset by peer (perhaps when dropped by a firewall/the server/...?).)

The setup

Prerequisities

To /etc/hosts add:

127.0.0.1       proxied.google.com

The toxiproxy setup

Start toxiproxy:

docker pull shopify/toxiproxy
# BEFORE we `run` it: case #3
docker run --rm -p 5555:5555 -p 6666:6666 -p 8474:8474 --name toxiproxy -it shopify/toxiproxy

Configure it (we could just POST to :8474 but using the CLI is easier):

$ docker exec -it toxiproxy /bin/sh
/ # cd /go/bin/
# ./toxiproxy-cli create google -l 0.0.0.0:6666 -u www.google.com:443 # BEFORE this is run: case #4
# ./toxiproxy-cli toxic add google -t latency -a latency=5000 # case #2
Added downstream latency toxic 'latency_downstream' on proxy 'google
# ./toxiproxy-cli toxic remove google -n latency_downstream
Removed toxic 'latency_downstream' on proxy 'google'

# ./toxiproxy-cli toxic add google -t  timeout -a timeout=2000 # case #2
Added downstream timeout toxic 'timeout_downstream' on proxy 'google'
# ./toxiproxy-cli toxic remove google -n timeout_downstream
Removed toxic 'timeout_downstream' on proxy 'google'

# ./toxiproxy-cli toxic add google -t limit_data -a bytes=5000 # case #5
Added downstream limit_data toxic 'limit_data_downstream' on proxy 'google'

The test code

(import '[java.net URL HttpURLConnection])
(->
  (doto ^HttpURLConnection (.openConnection (URL. "https://proxied.google.com:6666/"))
    ;; BEWARE: JVM *must* be started with `-Dsun.net.http.allowRestrictedHeaders=true` to allow setting the Host:
    (.setRequestProperty "Host" "www.google.com")
    (.setConnectTimeout 1000)
    (.setReadTimeout 1000))
  (.getInputStream)
  slurp)

Background

Read my Simulating network timeouts with toxiproxy to learn why we need to bother with /etc/hosts and the Host header.

view raw README.md hosted with ❤ by GitHub