about summary refs log tree commit homepage
path: root/test/benchmark/readinput.ru
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2019-05-12 22:11:12 +0000
committerEric Wong <e@80x24.org>2019-05-12 22:14:30 +0000
commitcaaf59f1e64310c7c7d7e514e932083972b079ca (patch)
tree8c84feb0b48abe21340ce45ea2d19fcc20184862 /test/benchmark/readinput.ru
parent4cbec67334d14d01f35818f7ac144de62ffebe4e (diff)
downloadunicorn-caaf59f1e64310c7c7d7e514e932083972b079ca.tar.gz
This is intended to demonstrate how badly we suck at dealing
with slow clients making uploads.  It can help users evaluate
alternative fully-buffering reverse proxies, because nginx
should not be the only option.
Diffstat (limited to 'test/benchmark/readinput.ru')
-rw-r--r--test/benchmark/readinput.ru40
1 files changed, 40 insertions, 0 deletions
diff --git a/test/benchmark/readinput.ru b/test/benchmark/readinput.ru
new file mode 100644
index 0000000..c91bec3
--- /dev/null
+++ b/test/benchmark/readinput.ru
@@ -0,0 +1,40 @@
+# This app is intended to test large HTTP requests with or without
+# a fully-buffering reverse proxy such as nginx. Without a fully-buffering
+# reverse proxy, unicorn will be unresponsive when client count exceeds
+# worker_processes.
+
+DOC = <<DOC
+To demonstrate how bad unicorn is at slowly uploading clients:
+
+  # in one terminal, start unicorn with one worker:
+  unicorn -E none -l 127.0.0.1:8080 test/benchmark/readinput.ru
+
+  # in a different terminal, upload 45M from multiple curl processes:
+  dd if=/dev/zero bs=45M count=1 | curl -T- -HExpect: --limit-rate 1M \
+     --trace-time -v http://127.0.0.1:8080/ &
+  dd if=/dev/zero bs=45M count=1 | curl -T- -HExpect: --limit-rate 1M \
+     --trace-time -v http://127.0.0.1:8080/ &
+  wait
+
+# The last client won't see a response until the first one is done uploading
+# You also won't be able to make GET requests to view this documentation
+# while clients are uploading.  You can also view the stderr debug output
+# of unicorn (see logging code in #{__FILE__}).
+DOC
+
+run(lambda do |env|
+  input = env['rack.input']
+  buf = ''.b
+
+  # default logger contains timestamps, rely on that so users can
+  # see what the server is doing
+  l = env['rack.logger']
+
+  l.debug('BEGIN reading input ...') if l
+  :nop while input.read(16384, buf)
+  l.debug('DONE reading input ...') if l
+
+  buf.clear
+  [ 200, [ %W(Content-Length #{DOC.size}), %w(Content-Type text/plain) ],
+    [ DOC ] ]
+end)