William, HAProxy says it was trying to establish a connection to the server. (I have not yet take a look at the pcap files)
Please add some timeouts in your defaults section: timeout connect 3s timeout server 30s timeout client 30s and run again the test, and let us know the logs generated by HAProxy. Baptiste On Tue, Sep 30, 2014 at 2:14 PM, William Lewis <[email protected]> wrote: > Hi Baptiste / Benjamin, > > I've attached haproxy log, and 3 pcap files > > The test with haproxy ended with me killing the node process, so the event > source request terminated and the hanging resource requests 503'd as shown at > the end of the log. > > Looking at the tcpdumps. > > 1. With haproxy > > * You can see that there are 6 concurrent http connections between iOS and > haproxy. > * In the first connection stream you can see the initial document, followed > by the event stream > * Then you can see the client has used http piping (pretty dumb considering > the browser should know this connection is occupied) to send requests for > /21.png /22.png /23.png ( the hanging resources) > * The first connection stream carried on responding with data from the event > source and the stuck resources are eventually 503'd when the node app is > killed > > 2. Without haproxy > > * This time we there are 12 distinct http connections that have been made > between iOS and node > * Again in the first connection stream you see the initial document followed > by the event stream and the pipelined requests for the same resources that go > stuck above > * However this time after the next event is emitted by the event stream, the > connection is terminated and carries on with a new connection > * And you see this in the browser console, but the event stream carries on > seamlessly > > > > > * The requests that were piped lined in that request get dealt with in other > streams e.g. /21.png is in stream 8 > > > I am by no means an expert analysing tcpdumps or how http pipelining is > supposed to work but it looks to me that without haproxy in the middle node > has managed to identify there are requests stuck in a http pipeline and reset > the connection to allow the browser to continue. Is there anyway to achieve > the same with haproxy? > > > > > > > > > > On 30 Sep 2014, at 12:21, Benjamin Lee <[email protected]> wrote: > >> On 30 September 2014 18:54, Baptiste <[email protected]> wrote: >>> >>> >>> >>> On Mon, Sep 29, 2014 at 9:15 PM, William Lewis <[email protected]> wrote: >>>> >>>> Hi all >>>> >>>> I have a problem with a website which uses Server-Sent Events where the >>>> long lived connection for the Server Events seems to be blocking other >>>> resources from loading on iOS clients only and only when I have haproxy >>>> between client and server. >>>> >>>> This is my test case. >>>> >>>> * Create a node express app which serves a html page which subscribes to >>>> an EventSource and asynchronously adds 200 300x100px images to the DOM >>>> * Node app is configured to serve resources with 500ms delay to reliably >>>> reproduce the problem >>>> * Configure basic haproxy between node app and client >>>> * Reset cache on iOS device and connect to server >>>> >>>> Expected result >>>> >>>> * Client open 5 simultaneous http connections to the server >>>> * 1 connection is blocked listening for events from the EventSource >>>> * The remaining 4 connections are used to download the 200 images >>>> >>>> Actual Result >>>> >>>> * Connection to EventSource is established and events start to be logged >>>> to the console >>>> * Images start to download on the page >>>> * Several of the images get blocked and never load >>>> >>>> >>>> Clearing the device cache and connecting directly to the server, all >>>> resources load, although the loading pattern of images is significantly >>>> different. >>>> >>>> If anyone has any ideas I would greatly appreciate any suggestions?? >>>> >>>> >>>> Sources and config included below. >>>> >>>> * index.html >>>> >>>> <html> >>>> <head> >>>> <style> >>>> img { >>>> width: 30px; >>>> height: 10px; >>>> border-style: solid; >>>> border-color: black; >>>> border-width: 1px; >>>> } >>>> </style> >>>> </head> >>>> <body> >>>> <script type="text/javascript"> >>>> var source = new EventSource('/events'); >>>> >>>> source.onmessage = function(e) { >>>> console.log(e.data); >>>> } >>>> >>>> var body = document.querySelectorAll('body'); >>>> var createImage = function(i) { >>>> var element = document.createElement('img'); >>>> element.src = '/' + i + '.png'; >>>> >>>> body[0].appendChild(element); >>>> } >>>> >>>> window.setTimeout(function() { >>>> for (var i = 1; i < 200; i++) { >>>> createImage(i); >>>> } >>>> }, 1000); >>>> </script> >>>> </body> >>>> </html> >>>> >>>> * app.js >>>> >>>> var express = require('express'); >>>> var app = express(); >>>> >>>> app.get('/events', function(req, res) { >>>> >>>> // let request last as long as possible >>>> req.socket.setTimeout(Infinity); >>>> >>>> var messageCount = 0; >>>> >>>> res.writeHead(200, { >>>> 'Content-Type': 'text/event-stream', >>>> 'Cache-Control': 'no-cache', >>>> 'Connection': 'keep-alive' >>>> }); >>>> res.write('\n'); >>>> >>>> var timeout; >>>> >>>> var emitEvent = function() { >>>> res.write('id:' + ++messageCount + '\n'); >>>> res.write('data:' + new Date().getTime() + '\n\n'); >>>> >>>> timeout = setTimeout(emitEvent, 3000); >>>> } >>>> >>>> req.on("close", function() { >>>> clearTimeout(timeout); >>>> }); >>>> >>>> emitEvent(); >>>> >>>> }); >>>> >>>> var staticHandler = express.static(__dirname + '/public'); >>>> >>>> app.use(function serveStatic(req, res, next) { >>>> setTimeout(function() { >>>> staticHandler(req, res, next); >>>> }, 500); >>>> }); >>>> >>>> var server = app.listen(3000, function() { >>>> console.log('Listening on port %d', server.address().port); >>>> }); >>>> >>>> >>>> * haproxy config >>>> >>>> global >>>> daemon >>>> quiet >>>> maxconn 1024 >>>> pidfile haproxy.pid >>>> log 127.0.0.1 local0 >>>> log 127.0.0.1 local1 notice >>>> >>>> defaults >>>> log global >>>> >>>> balance roundrobin >>>> mode http >>>> >>>> >>>> frontend external >>>> bind :80 >>>> default_backend test >>>> >>>> backend test >>>> server test localhost:3000 >>>> >>>> >>>> >>>> >>> >>> >>> Hi William, >>> >>> Could you please turn on option httplog and provide us the logs reported by >>> HAProxy? >>> Also, which version of HAProxy are you running? >>> >>> Baptiste >> >> >> Hi William, >> >> And, if possible, could you also please provide PCAP dumps for both scenarios >> >> 1. from both sides of haproxy >> 2. between IOS and your backend server >> >> ? >> >> -- >> Benjamin Lee mailto:[email protected] >> Melbourne, Australia http://www.realthought.net >> Linux / BSD / GNU tel:+61 4 16 BEN LEE >> <Screen Shot 2014-09-29 at 20.08.02.png> > >

