Perhaps this is a question about ab rather than about Tornado but something doesn't make sense.
I run the benchmark like this:
$ ab -n 100 http://localdomainname/ # 2 tornados being 1 nginx
...
Concurrency Level: 1
Time taken for tests: 0.162 seconds
Complete requests: 100
Failed requests: 17
(Connect: 0, Receive: 0, Length: 17, Exceptions: 0)
Write errors: 0
So according to that 17 of 100 requests failed.
Prior to running the benchamark I reset the log files and look at them again:
$ wc -l /tmp/gkc.access.log
100 /tmp/gkc.access.log
$ cat /tmp/gkc.access.log | grep ' 200 ' | wc -l
100
So, according to Nginx no requests failed! Why is ab saying 17 of 100 failed?
(By the way, 17 out of 100 was just one example. it goes up and down but never 0 which I'd expect)
UPDATE
Having tested with httperf without touching the Tornado+Nginx setup I get 0 failed requests.
You get the "length" failed requests, which does not mean that the response code was not 200. It just means that the length of response across requests was different (it remembers the length of the first one).
In detail this issue has been discussed in this question: Load Testing with AB ... fake failed requests (length)