-
Notifications
You must be signed in to change notification settings - Fork 189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Keepalive not working? #51
Comments
Thanks for the report! Can you please compile bjoern with debug output ( |
Hi Jonas, I was actually doing that as you replied :) Anyway, after further investigation, this seems to be an issue of standards implementation (and I am certainly no expert). But this is what I've observed (with the help of debug mode and tcpdumps): Curl (by default) sends an HTTP 1.1 request, but does not set a 'Connection: Keep-Alive' header, so bjoern closes the connection (confirmed by debug messages). Curl is designed to reuse connections, so it obviously expects them to be left open (when using HTTP1.1) without sending a the keep-alive header. I think keep-alive is supposed to be default in 1.1, so I'm not sure if this request header should be mandatory? Used pycurl to manually set this header and connections are reused successfully. ApacheBench sends HTTP 1.0 requests with the keep-alive header (required by 1.0), but expects a "Connection: keep-alive" response header, and hangs on the connection until it gets one (confirmed bjoern keeps connection alive until it times out). So the apachebench scenario is solved by explicitly setting the response header, which you can obviously do in the wsgi app code, e.g. my app changes to: import bjoern
def application(environ, start_response):
status = '200 OK'
output = 'Pong!'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(output))),
('Connection', 'keep-alive')]
start_response(status, response_headers)
return [output]
bjoern.listen(application, '192.168.1.190', 8081)
bjoern.run() I guess the question is, does the implementation in Bjoern need to change to meet the relevant standard? (RFC 2616?) |
Also, just confirmed the same issue exists when using httperf as the client (with http 1.1 and keep-alives). httperf does not consider setting the response header and so hits a connection reset error when bjoern closes. Command to test: httperf --hog --timeout=5 --client=0/1 --server=192.168.1.190 --port=8081 --uri=/ --rate=50000 --send-buffer=4096 --recv-buffer=16384 --num-conns=1 --num-calls=3 --http-version="1.1" ^attempts 3 requests on the same socket. |
Wow, thanks for the detailed analysis! I think that most HTTP/1.1 implementations indeed default to Keep-Alive and if you don't want to use it you have to return (Also I agree that HTTP connection should be completely abstracted away from WSGI apps, i.e. no fiddling with the |
If I set "connection: close" then Curl works as expected, not attempting to reuse the socket. I noticed from earlier packet captures that bjoern was not erroneously setting 'Connection: close'. The main issue seems to be that HTTP 1.1 connections aren't treated as persistent by default, even though the code in http-parser.c |
Testing with apachebench and curl; verbose output from curl, which you can see tries to reuse the connection:
Note the 'connection seems to be dead' line, and that the content of two responses seems to come all at once at the end ("Pong!Pong!"), rather than displayed inline with the request as Curl would normally do.
apachebench with -k flag will just hang after making a connection (presumably after the first request is served).
Here's my test app:
Testing with the latest code base.
Worth noting that Curl does not pipeline requests, it's waiting for the response before sending the second request.
The text was updated successfully, but these errors were encountered: