Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does the browser freeze when executing many ajax requests?

I have a page that is executing around 200 ajax requests using jquery.load but it is behaving in a very un-ajax way because the browser is frozen while the results are fetched.

By freezing I mean losing control of the browser, not able to scroll it up and down even. Then the results all display at once when it has finished all requests, but I know it is actually fetching the results 6 at a time (browser controlled "same host" policy) from watching the access log of the target server.

Though the jquery.load commands are built using a "foreach" loop they are already written to the source of the page when the user loads it (so for all intents and purposes they could all be hand written individually), so its not like the page is waiting for the loop to finish. The last "symptom" is that even if it is only 30 requests instead, the issue is just the same.

So it's odd to me and I am looking for ideas of what could cause this and how it could be worked around. It's definitely confusing to the end user especially as it could take 90-100 seconds until all the responses are back and the user regains control of the browser.

One small update:

I have very similar code running in another webapp that does around 20 requests simultaneously without issue. The difference is that instead of fetching a page, it is ssh'ing to the server and reading/updating a file on the file system via a script. I would have thought that would actually have a little more overhead but it has none of these issues.

And as I have said - even 20 requests causes the same issue with the code in question... so I am tempted to think its perhaps curl related... though its pure speculation.

The Bigger update Now with infinitely more Code!!!

The fuller background to app is this. We run a cluster of some of the highest trafficked WebSphere AppServers in the world, which are running our Commerce applications. The intensity of the traffic means that if we simply let traffic on to an appserver before the JVM is warmed up, they crash! So we hit a few key pages before allowing traffic on, as this precompiles all the major servlets, proportions the JVM, and populates some of the servlet caches. Then the traffic can come onto the server with no issues and they run great.

We had a version of the app written in CGI which worked but was so slow due to being synchronous. We are talking about 10 minutes on some clusters to run. Due to being synchronous requests, only one thread on the appserver and one jdbc connection was being used.

So what the new webapp does is use a template of these key pages, to combine with a bunch of market definitions (country code, language code, catalog id's etc) to produce a list of all those URL's that need to be hit. By hitting them all in an asynchronous way it not only runs faster (now taking only 90 seconds), it also does a better job of proportioning the JVM, uses up to 30 threads and opens the JDBC pool to its full number of connections. Thus it's REALLY in a production-like state by the time we let traffic on. So I am very pleased with results, but this browser freeze is annoying me from a purely cosmetic and puzzle-solving point of view.

So now some code, the user simply selects an appserver, the app decides which cluster it is from, and displays the list of computed URL's it will hit. At this point the page is a table of 'Markets x Urls' with each cell having a unique id that the jquery uses to put the right result in the right cell (as we can't guarantee the order in which the results come back - nor do we want to as that takes us back into synchronous territory again.

So at the point at which the user is ready to click Go, the table is written and the jQuery commands prepared. On clicking go the jquery script is executed and URL's are hit and return a HTTP status code for each so we know they were successful.

The JQ part generated looks like (shortened to just a few markets)

$("a#submit").click(function(event) {
    alert(" booya ");
    $("#sesv-1").load("psurl.php?server=servera.domain.com&url=/se/sv");
    $("#sesv-2").load("psurl.php?server=servera.domain.com&url=/se/sv/catalog/productsaz/");
    $("#sesv-3").load("psurl.php?server=servera.domain.com&url=/se/sv/catalog/products/12345678");
    $("#sesv-4").load("psurl.php?server=servera.domain.com&url=/webapp/wcs/stores/servlet/StockSearch?storeId=14&productId=103406&StoreNumber=099&langId=-13&ddkey=http:StockSearch");
    $("#sesv-5").load("psurl.php?server=servera.domain.com&url=/webapp/wcs/stores/servlet/StockSearch?query=testProd&storeId=14&langId=-11&StoreNumber=011");
    $("#atde-1").load("psurl.php?server=servera.domain.com&url=/at/de");
    $("#atde-2").load("psurl.php?server=servera.domain.com&url=/at/de/catalog/productsaz/");
    $("#atde-3").load("psurl.php?server=servera.domain.com&url=/at/de/catalog/products/12345678");
    $("#atde-4").load("psurl.php?server=servera.domain.com&url=/webapp/wcs/stores/servlet/StockSearch?storeId=1&productId=103406&StoreNumber=114&langId=-99&ddkey=http:StockSearch");
    $("#atde-5").load("psurl.php?server=servera.domain.com&url=/webapp/wcs/stores/servlet/StockSearch?query=testProd&storeId=1&langId=-21&StoreNumber=273");
    $("#benl-1").load("psurl.php?server=servera.domain.com&url=/be/nl");
    $("#benl-2").load("psurl.php?server=servera.domain.com&url=/be/nl/catalog/productsaz/");
    $("#benl-3").load("psurl.php?server=servera.domain.com&url=/be/nl/catalog/products/12345678");
    $("#benl-4").load("psurl.php?server=servera.domain.com&url=/webapp/wcs/stores/servlet/StockSearch?storeId=18&productId=103406&StoreNumber=412&langId=-44&ddkey=http:StockSearch");
    $("#benl-5").load("psurl.php?server=servera.domain.com&url=/webapp/wcs/stores/servlet/StockSearch?query=testProd&storeId=18&langId=-23&StoreNumber=482");
    $("#befr-1").load("psurl.php?server=servera.domain.com&url=/be/fr");
    $("#befr-2").load("psurl.php?server=servera.domain.com&url=/be/fr/catalog/productsaz/");
    $("#befr-3").load("psurl.php?server=servera.domain.com&url=/be/fr/catalog/products/12345678");
    $("#befr-4").load("psurl.php?server=servera.domain.com&url=/webapp/wcs/stores/servlet/StockSearch?storeId=130&productId=103406&StoreNumber=048&langId=-73&ddkey=http:StockSearch");
    $("#befr-5").load("psurl.php?server=servera.domain.com&url=/webapp/wcs/stores/servlet/StockSearch?query=testProd&storeId=130&langId=-24&StoreNumber=482");
    $("#caen-1").load("psurl.php?server=servera.domain.com&url=/ca/en");
    $("#caen-2").load("psurl.php?server=servera.domain.com&url=/ca/en/catalog/productsaz/");
    $("#caen-3").load("psurl.php?server=servera.domain.com&url=/ca/en/catalog/products/12345678");
    $("#caen-4").load("psurl.php?server=servera.domain.com&url=/webapp/wcs/stores/servlet/StockSearch?storeId=30&productId=103406&StoreNumber=006&langId=-11&ddkey=http:StockSearch");
    $("#caen-5").load("psurl.php?server=servera.domain.com&url=/webapp/wcs/stores/servlet/StockSearch?query=testProd&storeId=30&langId=-15&StoreNumber=216");
    $("#cafr-1").load("psurl.php?server=servera.domain.com&url=/ca/fr");
    $("#cafr-2").load("psurl.php?server=servera.domain.com&url=/ca/fr/catalog/productsaz/");
    $("#cafr-3").load("psurl.php?server=servera.domain.com&url=/ca/fr/catalog/products/12345678");
    $("#cafr-4").load("psurl.php?server=servera.domain.com&url=/webapp/wcs/stores/servlet/StockSearch?storeId=33&productId=103406&StoreNumber=124&langId=-09&ddkey=http:StockSearch");
    $("#cafr-5").load("psurl.php?server=servera.domain.com&url=/webapp/wcs/stores/servlet/StockSearch?query=testProd&storeId=33&langId=-16&StoreNumber=216")
    });
});

The PS URL is simply a curl request function that responds with 404, 200, 500 etc which is then used to populate the relevant cell.

function getPage( $url ) {
$options = array(
    CURLOPT_URL             => $url,
    CURLOPT_RETURNTRANSFER => true,                 // return web page
    CURLOPT_HEADER         => true,                 // return headers
    CURLOPT_FOLLOWLOCATION => true,                 // follow redirects
    CURLOPT_ENCODING       => "",                   // handle all encodings
    CURLOPT_USERAGENT      => "pre-surf",           // who am i
    CURLOPT_AUTOREFERER    => true,                 // set referer on redirect
    CURLOPT_CONNECTTIMEOUT => 120,                  // timeout on connect
    CURLOPT_TIMEOUT        => 120,                  // timeout on response
    CURLOPT_MAXREDIRS      => 10,                   // stop after 10 redirects
    CURLOPT_POST            => 0,                   // i am not sending post data
    CURLOPT_SSL_VERIFYHOST => 0,                    // don't verify ssl
    CURLOPT_SSL_VERIFYPEER => FALSE,                //
);

$ch      = curl_init();
curl_setopt_array($ch, $options);
$content = curl_exec($ch);
$err     = curl_errno($ch);
$errmsg  = curl_error($ch) ;
$header  = curl_getinfo($ch);
curl_close($ch);

//  $header['errno']   = $err;
//  $header['errmsg']  = $errmsg;
//  $header['content'] = $content;
return $header['http_status_code'];
}
like image 357
Seer Avatar asked Oct 09 '22 14:10

Seer


1 Answers

The problem here is not the Ajax requests, the problem is each one of those requests is updating the DOM. The browser redraw is what is causing the browser to lock up.

You need to find a better solution that does not write to the DOM so often.

like image 142
epascarello Avatar answered Oct 11 '22 03:10

epascarello